From 09f55f5167efb53e2816158a7e68bea8f3497d08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Vinot?= Date: Tue, 14 Nov 2023 12:23:03 +0100 Subject: [PATCH 01/80] fix: Avoid confusing error when an auth key is limited to an IP Fix #1099 --- pymisp/api.py | 15 +++++++++++++-- pyproject.toml | 8 ++++---- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/pymisp/api.py b/pymisp/api.py index 83935ff..216610a 100644 --- a/pymisp/api.py +++ b/pymisp/api.py @@ -207,7 +207,18 @@ class PyMISP: self._current_user: MISPUser self._current_role: MISPRole self._current_user_settings: List[MISPUserSetting] - self._current_user, self._current_role, self._current_user_settings = self.get_user(pythonify=True, expanded=True) + user_infos = self.get_user(pythonify=True, expanded=True) + if isinstance(user_infos, dict): + # There was an error during the get_user call + if e := user_infos.get('errors'): + raise PyMISPError(f'Unable to get the user settings: {e}') + raise PyMISPError(f'Unexpected error when initializing the connection: {user_infos}') + elif len(user_infos) == 3: + self._current_user, self._current_role, self._current_user_settings = user_infos + else: + raise PyMISPError(f'Unexpected error when initializing the connection: {user_infos}') + except PyMISPError as e: + raise e except Exception as e: raise PyMISPError(f'Unable to connect to MISP ({self.root_url}). Please make sure the API key and the URL are correct (http/https is required): {e}') @@ -2253,7 +2264,7 @@ class PyMISP: :param user: user to get; `me` means the owner of the API key doing the query :param pythonify: Returns a PyMISP Object instead of the plain json output - :param expanded: Also returns a MISPRole and a MISPUserSetting + :param expanded: Also returns a MISPRole and a MISPUserSetting. Only taken in account if pythonify is True. """ user_id = get_uuid_or_id_from_abstract_misp(user) r = self._prepare_request('GET', f'users/view/{user_id}') diff --git a/pyproject.toml b/pyproject.toml index 1258197..3c01e8c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -53,11 +53,11 @@ pydeep2 = {version = "^0.5.1", optional = true} lief = {version = "^0.13.2", optional = true} beautifulsoup4 = {version = "^4.12.2", optional = true} validators = {version = "^0.22.0", optional = true} -sphinx-autodoc-typehints = {version = "^1.24.0", optional = true} +sphinx-autodoc-typehints = {version = "^1.24.1", optional = true} recommonmark = {version = "^0.7.1", optional = true} reportlab = {version = "^4.0.6", optional = true} pyfaup = {version = "^1.2", optional = true} -publicsuffixlist = {version = "^0.10.0.20231022", optional = true} +publicsuffixlist = {version = "^0.10.0.20231104", optional = true} urllib3 = {extras = ["brotli"], version = "*", optional = true} Sphinx = [ {version = "<7.2", python = "<3.9", optional = true}, @@ -81,10 +81,10 @@ ipython = [ {version = "<8.13.0", python = "<3.9"}, {version = "^8.13.0", python = ">=3.9"} ] -jupyterlab = "^4.0.7" +jupyterlab = "^4.0.8" types-requests = "^2.31.0.10" types-python-dateutil = "^2.8.19.14" -types-redis = "^4.6.0.7" +types-redis = "^4.6.0.9" types-Flask = "^1.1.6" pytest-cov = "^4.1.0" From 64d9f35266625de75099909d929098539763f116 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Vinot?= Date: Tue, 14 Nov 2023 12:26:13 +0100 Subject: [PATCH 02/80] chg: Bump deps --- poetry.lock | 878 +++++++++++++++++++++++++------------------------ pyproject.toml | 10 +- 2 files changed, 449 insertions(+), 439 deletions(-) diff --git a/poetry.lock b/poetry.lock index 7203e30..9386f66 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.6.1 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.7.0 and should not be changed by hand. [[package]] name = "alabaster" @@ -121,20 +121,21 @@ test = ["dateparser (==1.*)", "pre-commit", "pytest", "pytest-cov", "pytest-mock [[package]] name = "asttokens" -version = "2.4.0" +version = "2.4.1" description = "Annotate AST trees with source code positions" optional = false python-versions = "*" files = [ - {file = "asttokens-2.4.0-py2.py3-none-any.whl", hash = "sha256:cf8fc9e61a86461aa9fb161a14a0841a03c405fa829ac6b202670b3495d2ce69"}, - {file = "asttokens-2.4.0.tar.gz", hash = "sha256:2e0171b991b2c959acc6c49318049236844a5da1d65ba2672c4880c1c894834e"}, + {file = "asttokens-2.4.1-py2.py3-none-any.whl", hash = "sha256:051ed49c3dcae8913ea7cd08e46a606dba30b79993209636c4875bc1d637bc24"}, + {file = "asttokens-2.4.1.tar.gz", hash = "sha256:b03869718ba9a6eb027e134bfdf69f38a236d681c83c160d510768af11254ba0"}, ] [package.dependencies] six = ">=1.12.0" [package.extras] -test = ["astroid", "pytest"] +astroid = ["astroid (>=1,<2)", "astroid (>=2,<4)"] +test = ["astroid (>=1,<2)", "astroid (>=2,<4)", "pytest"] [[package]] name = "async-lru" @@ -170,17 +171,18 @@ tests-no-zope = ["cloudpickle", "hypothesis", "mypy (>=1.1.1)", "pympler", "pyte [[package]] name = "babel" -version = "2.13.0" +version = "2.13.1" description = "Internationalization utilities" optional = false python-versions = ">=3.7" files = [ - {file = "Babel-2.13.0-py3-none-any.whl", hash = "sha256:fbfcae1575ff78e26c7449136f1abbefc3c13ce542eeb13d43d50d8b047216ec"}, - {file = "Babel-2.13.0.tar.gz", hash = "sha256:04c3e2d28d2b7681644508f836be388ae49e0cfe91465095340395b60d00f210"}, + {file = "Babel-2.13.1-py3-none-any.whl", hash = "sha256:7077a4984b02b6727ac10f1f7294484f737443d7e2e66c5e4380e41a3ae0b4ed"}, + {file = "Babel-2.13.1.tar.gz", hash = "sha256:33e0952d7dd6374af8dbf6768cc4ddf3ccfefc244f9986d4074704f2fbd18900"}, ] [package.dependencies] pytz = {version = ">=2015.7", markers = "python_version < \"3.9\""} +setuptools = {version = "*", markers = "python_version >= \"3.12\""} [package.extras] dev = ["freezegun (>=1.0,<2.0)", "pytest (>=6.0)", "pytest-cov"] @@ -468,101 +470,101 @@ pycparser = "*" [[package]] name = "charset-normalizer" -version = "3.3.1" +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.1.tar.gz", hash = "sha256:d9137a876020661972ca6eec0766d81aef8a5627df628b664b234b73396e727e"}, - {file = "charset_normalizer-3.3.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:8aee051c89e13565c6bd366813c386939f8e928af93c29fda4af86d25b73d8f8"}, - {file = "charset_normalizer-3.3.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:352a88c3df0d1fa886562384b86f9a9e27563d4704ee0e9d56ec6fcd270ea690"}, - {file = "charset_normalizer-3.3.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:223b4d54561c01048f657fa6ce41461d5ad8ff128b9678cfe8b2ecd951e3f8a2"}, - {file = "charset_normalizer-3.3.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4f861d94c2a450b974b86093c6c027888627b8082f1299dfd5a4bae8e2292821"}, - {file = "charset_normalizer-3.3.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1171ef1fc5ab4693c5d151ae0fdad7f7349920eabbaca6271f95969fa0756c2d"}, - {file = "charset_normalizer-3.3.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28f512b9a33235545fbbdac6a330a510b63be278a50071a336afc1b78781b147"}, - {file = "charset_normalizer-3.3.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0e842112fe3f1a4ffcf64b06dc4c61a88441c2f02f373367f7b4c1aa9be2ad5"}, - {file = "charset_normalizer-3.3.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3f9bc2ce123637a60ebe819f9fccc614da1bcc05798bbbaf2dd4ec91f3e08846"}, - {file = "charset_normalizer-3.3.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:f194cce575e59ffe442c10a360182a986535fd90b57f7debfaa5c845c409ecc3"}, - {file = "charset_normalizer-3.3.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:9a74041ba0bfa9bc9b9bb2cd3238a6ab3b7618e759b41bd15b5f6ad958d17605"}, - {file = "charset_normalizer-3.3.1-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:b578cbe580e3b41ad17b1c428f382c814b32a6ce90f2d8e39e2e635d49e498d1"}, - {file = "charset_normalizer-3.3.1-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:6db3cfb9b4fcecb4390db154e75b49578c87a3b9979b40cdf90d7e4b945656e1"}, - {file = "charset_normalizer-3.3.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:debb633f3f7856f95ad957d9b9c781f8e2c6303ef21724ec94bea2ce2fcbd056"}, - {file = "charset_normalizer-3.3.1-cp310-cp310-win32.whl", hash = "sha256:87071618d3d8ec8b186d53cb6e66955ef2a0e4fa63ccd3709c0c90ac5a43520f"}, - {file = "charset_normalizer-3.3.1-cp310-cp310-win_amd64.whl", hash = "sha256:e372d7dfd154009142631de2d316adad3cc1c36c32a38b16a4751ba78da2a397"}, - {file = "charset_normalizer-3.3.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ae4070f741f8d809075ef697877fd350ecf0b7c5837ed68738607ee0a2c572cf"}, - {file = "charset_normalizer-3.3.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:58e875eb7016fd014c0eea46c6fa92b87b62c0cb31b9feae25cbbe62c919f54d"}, - {file = "charset_normalizer-3.3.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:dbd95e300367aa0827496fe75a1766d198d34385a58f97683fe6e07f89ca3e3c"}, - {file = "charset_normalizer-3.3.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:de0b4caa1c8a21394e8ce971997614a17648f94e1cd0640fbd6b4d14cab13a72"}, - {file = "charset_normalizer-3.3.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:985c7965f62f6f32bf432e2681173db41336a9c2611693247069288bcb0c7f8b"}, - {file = "charset_normalizer-3.3.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a15c1fe6d26e83fd2e5972425a772cca158eae58b05d4a25a4e474c221053e2d"}, - {file = "charset_normalizer-3.3.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ae55d592b02c4349525b6ed8f74c692509e5adffa842e582c0f861751701a673"}, - {file = "charset_normalizer-3.3.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:be4d9c2770044a59715eb57c1144dedea7c5d5ae80c68fb9959515037cde2008"}, - {file = "charset_normalizer-3.3.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:851cf693fb3aaef71031237cd68699dded198657ec1e76a76eb8be58c03a5d1f"}, - {file = "charset_normalizer-3.3.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:31bbaba7218904d2eabecf4feec0d07469284e952a27400f23b6628439439fa7"}, - {file = "charset_normalizer-3.3.1-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:871d045d6ccc181fd863a3cd66ee8e395523ebfbc57f85f91f035f50cee8e3d4"}, - {file = "charset_normalizer-3.3.1-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:501adc5eb6cd5f40a6f77fbd90e5ab915c8fd6e8c614af2db5561e16c600d6f3"}, - {file = "charset_normalizer-3.3.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:f5fb672c396d826ca16a022ac04c9dce74e00a1c344f6ad1a0fdc1ba1f332213"}, - {file = "charset_normalizer-3.3.1-cp311-cp311-win32.whl", hash = "sha256:bb06098d019766ca16fc915ecaa455c1f1cd594204e7f840cd6258237b5079a8"}, - {file = "charset_normalizer-3.3.1-cp311-cp311-win_amd64.whl", hash = "sha256:8af5a8917b8af42295e86b64903156b4f110a30dca5f3b5aedea123fbd638bff"}, - {file = "charset_normalizer-3.3.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:7ae8e5142dcc7a49168f4055255dbcced01dc1714a90a21f87448dc8d90617d1"}, - {file = "charset_normalizer-3.3.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:5b70bab78accbc672f50e878a5b73ca692f45f5b5e25c8066d748c09405e6a55"}, - {file = "charset_normalizer-3.3.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5ceca5876032362ae73b83347be8b5dbd2d1faf3358deb38c9c88776779b2e2f"}, - {file = "charset_normalizer-3.3.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:34d95638ff3613849f473afc33f65c401a89f3b9528d0d213c7037c398a51296"}, - {file = "charset_normalizer-3.3.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9edbe6a5bf8b56a4a84533ba2b2f489d0046e755c29616ef8830f9e7d9cf5728"}, - {file = "charset_normalizer-3.3.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f6a02a3c7950cafaadcd46a226ad9e12fc9744652cc69f9e5534f98b47f3bbcf"}, - {file = "charset_normalizer-3.3.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:10b8dd31e10f32410751b3430996f9807fc4d1587ca69772e2aa940a82ab571a"}, - {file = "charset_normalizer-3.3.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:edc0202099ea1d82844316604e17d2b175044f9bcb6b398aab781eba957224bd"}, - {file = "charset_normalizer-3.3.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:b891a2f68e09c5ef989007fac11476ed33c5c9994449a4e2c3386529d703dc8b"}, - {file = "charset_normalizer-3.3.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:71ef3b9be10070360f289aea4838c784f8b851be3ba58cf796262b57775c2f14"}, - {file = "charset_normalizer-3.3.1-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:55602981b2dbf8184c098bc10287e8c245e351cd4fdcad050bd7199d5a8bf514"}, - {file = "charset_normalizer-3.3.1-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:46fb9970aa5eeca547d7aa0de5d4b124a288b42eaefac677bde805013c95725c"}, - {file = "charset_normalizer-3.3.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:520b7a142d2524f999447b3a0cf95115df81c4f33003c51a6ab637cbda9d0bf4"}, - {file = "charset_normalizer-3.3.1-cp312-cp312-win32.whl", hash = "sha256:8ec8ef42c6cd5856a7613dcd1eaf21e5573b2185263d87d27c8edcae33b62a61"}, - {file = "charset_normalizer-3.3.1-cp312-cp312-win_amd64.whl", hash = "sha256:baec8148d6b8bd5cee1ae138ba658c71f5b03e0d69d5907703e3e1df96db5e41"}, - {file = "charset_normalizer-3.3.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:63a6f59e2d01310f754c270e4a257426fe5a591dc487f1983b3bbe793cf6bac6"}, - {file = "charset_normalizer-3.3.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1d6bfc32a68bc0933819cfdfe45f9abc3cae3877e1d90aac7259d57e6e0f85b1"}, - {file = "charset_normalizer-3.3.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4f3100d86dcd03c03f7e9c3fdb23d92e32abbca07e7c13ebd7ddfbcb06f5991f"}, - {file = "charset_normalizer-3.3.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:39b70a6f88eebe239fa775190796d55a33cfb6d36b9ffdd37843f7c4c1b5dc67"}, - {file = "charset_normalizer-3.3.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4e12f8ee80aa35e746230a2af83e81bd6b52daa92a8afaef4fea4a2ce9b9f4fa"}, - {file = "charset_normalizer-3.3.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7b6cefa579e1237ce198619b76eaa148b71894fb0d6bcf9024460f9bf30fd228"}, - {file = "charset_normalizer-3.3.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:61f1e3fb621f5420523abb71f5771a204b33c21d31e7d9d86881b2cffe92c47c"}, - {file = "charset_normalizer-3.3.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:4f6e2a839f83a6a76854d12dbebde50e4b1afa63e27761549d006fa53e9aa80e"}, - {file = "charset_normalizer-3.3.1-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:1ec937546cad86d0dce5396748bf392bb7b62a9eeb8c66efac60e947697f0e58"}, - {file = "charset_normalizer-3.3.1-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:82ca51ff0fc5b641a2d4e1cc8c5ff108699b7a56d7f3ad6f6da9dbb6f0145b48"}, - {file = "charset_normalizer-3.3.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:633968254f8d421e70f91c6ebe71ed0ab140220469cf87a9857e21c16687c034"}, - {file = "charset_normalizer-3.3.1-cp37-cp37m-win32.whl", hash = "sha256:c0c72d34e7de5604df0fde3644cc079feee5e55464967d10b24b1de268deceb9"}, - {file = "charset_normalizer-3.3.1-cp37-cp37m-win_amd64.whl", hash = "sha256:63accd11149c0f9a99e3bc095bbdb5a464862d77a7e309ad5938fbc8721235ae"}, - {file = "charset_normalizer-3.3.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5a3580a4fdc4ac05f9e53c57f965e3594b2f99796231380adb2baaab96e22761"}, - {file = "charset_normalizer-3.3.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2465aa50c9299d615d757c1c888bc6fef384b7c4aec81c05a0172b4400f98557"}, - {file = "charset_normalizer-3.3.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:cb7cd68814308aade9d0c93c5bd2ade9f9441666f8ba5aa9c2d4b389cb5e2a45"}, - {file = "charset_normalizer-3.3.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:91e43805ccafa0a91831f9cd5443aa34528c0c3f2cc48c4cb3d9a7721053874b"}, - {file = "charset_normalizer-3.3.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:854cc74367180beb327ab9d00f964f6d91da06450b0855cbbb09187bcdb02de5"}, - {file = "charset_normalizer-3.3.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c15070ebf11b8b7fd1bfff7217e9324963c82dbdf6182ff7050519e350e7ad9f"}, - {file = "charset_normalizer-3.3.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2c4c99f98fc3a1835af8179dcc9013f93594d0670e2fa80c83aa36346ee763d2"}, - {file = "charset_normalizer-3.3.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3fb765362688821404ad6cf86772fc54993ec11577cd5a92ac44b4c2ba52155b"}, - {file = "charset_normalizer-3.3.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:dced27917823df984fe0c80a5c4ad75cf58df0fbfae890bc08004cd3888922a2"}, - {file = "charset_normalizer-3.3.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a66bcdf19c1a523e41b8e9d53d0cedbfbac2e93c649a2e9502cb26c014d0980c"}, - {file = "charset_normalizer-3.3.1-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:ecd26be9f112c4f96718290c10f4caea6cc798459a3a76636b817a0ed7874e42"}, - {file = "charset_normalizer-3.3.1-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:3f70fd716855cd3b855316b226a1ac8bdb3caf4f7ea96edcccc6f484217c9597"}, - {file = "charset_normalizer-3.3.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:17a866d61259c7de1bdadef418a37755050ddb4b922df8b356503234fff7932c"}, - {file = "charset_normalizer-3.3.1-cp38-cp38-win32.whl", hash = "sha256:548eefad783ed787b38cb6f9a574bd8664468cc76d1538215d510a3cd41406cb"}, - {file = "charset_normalizer-3.3.1-cp38-cp38-win_amd64.whl", hash = "sha256:45f053a0ece92c734d874861ffe6e3cc92150e32136dd59ab1fb070575189c97"}, - {file = "charset_normalizer-3.3.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:bc791ec3fd0c4309a753f95bb6c749ef0d8ea3aea91f07ee1cf06b7b02118f2f"}, - {file = "charset_normalizer-3.3.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:0c8c61fb505c7dad1d251c284e712d4e0372cef3b067f7ddf82a7fa82e1e9a93"}, - {file = "charset_normalizer-3.3.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:2c092be3885a1b7899cd85ce24acedc1034199d6fca1483fa2c3a35c86e43041"}, - {file = "charset_normalizer-3.3.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c2000c54c395d9e5e44c99dc7c20a64dc371f777faf8bae4919ad3e99ce5253e"}, - {file = "charset_normalizer-3.3.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4cb50a0335382aac15c31b61d8531bc9bb657cfd848b1d7158009472189f3d62"}, - {file = "charset_normalizer-3.3.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c30187840d36d0ba2893bc3271a36a517a717f9fd383a98e2697ee890a37c273"}, - {file = "charset_normalizer-3.3.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fe81b35c33772e56f4b6cf62cf4aedc1762ef7162a31e6ac7fe5e40d0149eb67"}, - {file = "charset_normalizer-3.3.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d0bf89afcbcf4d1bb2652f6580e5e55a840fdf87384f6063c4a4f0c95e378656"}, - {file = "charset_normalizer-3.3.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:06cf46bdff72f58645434d467bf5228080801298fbba19fe268a01b4534467f5"}, - {file = "charset_normalizer-3.3.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:3c66df3f41abee950d6638adc7eac4730a306b022570f71dd0bd6ba53503ab57"}, - {file = "charset_normalizer-3.3.1-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:cd805513198304026bd379d1d516afbf6c3c13f4382134a2c526b8b854da1c2e"}, - {file = "charset_normalizer-3.3.1-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:9505dc359edb6a330efcd2be825fdb73ee3e628d9010597aa1aee5aa63442e97"}, - {file = "charset_normalizer-3.3.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:31445f38053476a0c4e6d12b047b08ced81e2c7c712e5a1ad97bc913256f91b2"}, - {file = "charset_normalizer-3.3.1-cp39-cp39-win32.whl", hash = "sha256:bd28b31730f0e982ace8663d108e01199098432a30a4c410d06fe08fdb9e93f4"}, - {file = "charset_normalizer-3.3.1-cp39-cp39-win_amd64.whl", hash = "sha256:555fe186da0068d3354cdf4bbcbc609b0ecae4d04c921cc13e209eece7720727"}, - {file = "charset_normalizer-3.3.1-py3-none-any.whl", hash = "sha256:800561453acdecedaac137bf09cd719c7a440b6800ec182f077bb8e7025fb708"}, + {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]] @@ -589,22 +591,20 @@ files = [ [[package]] name = "comm" -version = "0.1.4" +version = "0.2.0" description = "Jupyter Python Comm implementation, for usage in ipykernel, xeus-python etc." optional = false -python-versions = ">=3.6" +python-versions = ">=3.8" files = [ - {file = "comm-0.1.4-py3-none-any.whl", hash = "sha256:6d52794cba11b36ed9860999cd10fd02d6b2eac177068fdd585e1e2f8a96e67a"}, - {file = "comm-0.1.4.tar.gz", hash = "sha256:354e40a59c9dd6db50c5cc6b4acc887d82e9603787f83b68c01a80a923984d15"}, + {file = "comm-0.2.0-py3-none-any.whl", hash = "sha256:2da8d9ebb8dd7bfc247adaff99f24dce705638a8042b85cb995066793e391001"}, + {file = "comm-0.2.0.tar.gz", hash = "sha256:a517ea2ca28931c7007a7a99c562a0fa5883cfb48963140cf642c41c948498be"}, ] [package.dependencies] traitlets = ">=4" [package.extras] -lint = ["black (>=22.6.0)", "mdformat (>0.7)", "mdformat-gfm (>=0.3.5)", "ruff (>=0.0.156)"] test = ["pytest"] -typing = ["mypy (>=0.990)"] [[package]] name = "commonmark" @@ -699,34 +699,34 @@ toml = ["tomli"] [[package]] name = "cryptography" -version = "41.0.4" +version = "41.0.5" description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." optional = false python-versions = ">=3.7" files = [ - {file = "cryptography-41.0.4-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:80907d3faa55dc5434a16579952ac6da800935cd98d14dbd62f6f042c7f5e839"}, - {file = "cryptography-41.0.4-cp37-abi3-macosx_10_12_x86_64.whl", hash = "sha256:35c00f637cd0b9d5b6c6bd11b6c3359194a8eba9c46d4e875a3660e3b400005f"}, - {file = "cryptography-41.0.4-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cecfefa17042941f94ab54f769c8ce0fe14beff2694e9ac684176a2535bf9714"}, - {file = "cryptography-41.0.4-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e40211b4923ba5a6dc9769eab704bdb3fbb58d56c5b336d30996c24fcf12aadb"}, - {file = "cryptography-41.0.4-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:23a25c09dfd0d9f28da2352503b23e086f8e78096b9fd585d1d14eca01613e13"}, - {file = "cryptography-41.0.4-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:2ed09183922d66c4ec5fdaa59b4d14e105c084dd0febd27452de8f6f74704143"}, - {file = "cryptography-41.0.4-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:5a0f09cefded00e648a127048119f77bc2b2ec61e736660b5789e638f43cc397"}, - {file = "cryptography-41.0.4-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:9eeb77214afae972a00dee47382d2591abe77bdae166bda672fb1e24702a3860"}, - {file = "cryptography-41.0.4-cp37-abi3-win32.whl", hash = "sha256:3b224890962a2d7b57cf5eeb16ccaafba6083f7b811829f00476309bce2fe0fd"}, - {file = "cryptography-41.0.4-cp37-abi3-win_amd64.whl", hash = "sha256:c880eba5175f4307129784eca96f4e70b88e57aa3f680aeba3bab0e980b0f37d"}, - {file = "cryptography-41.0.4-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:004b6ccc95943f6a9ad3142cfabcc769d7ee38a3f60fb0dddbfb431f818c3a67"}, - {file = "cryptography-41.0.4-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:86defa8d248c3fa029da68ce61fe735432b047e32179883bdb1e79ed9bb8195e"}, - {file = "cryptography-41.0.4-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:37480760ae08065437e6573d14be973112c9e6dcaf5f11d00147ee74f37a3829"}, - {file = "cryptography-41.0.4-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:b5f4dfe950ff0479f1f00eda09c18798d4f49b98f4e2006d644b3301682ebdca"}, - {file = "cryptography-41.0.4-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:7e53db173370dea832190870e975a1e09c86a879b613948f09eb49324218c14d"}, - {file = "cryptography-41.0.4-pp38-pypy38_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:5b72205a360f3b6176485a333256b9bcd48700fc755fef51c8e7e67c4b63e3ac"}, - {file = "cryptography-41.0.4-pp38-pypy38_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:93530900d14c37a46ce3d6c9e6fd35dbe5f5601bf6b3a5c325c7bffc030344d9"}, - {file = "cryptography-41.0.4-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:efc8ad4e6fc4f1752ebfb58aefece8b4e3c4cae940b0994d43649bdfce8d0d4f"}, - {file = "cryptography-41.0.4-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:c3391bd8e6de35f6f1140e50aaeb3e2b3d6a9012536ca23ab0d9c35ec18c8a91"}, - {file = "cryptography-41.0.4-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:0d9409894f495d465fe6fda92cb70e8323e9648af912d5b9141d616df40a87b8"}, - {file = "cryptography-41.0.4-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:8ac4f9ead4bbd0bc8ab2d318f97d85147167a488be0e08814a37eb2f439d5cf6"}, - {file = "cryptography-41.0.4-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:047c4603aeb4bbd8db2756e38f5b8bd7e94318c047cfe4efeb5d715e08b49311"}, - {file = "cryptography-41.0.4.tar.gz", hash = "sha256:7febc3094125fc126a7f6fb1f420d0da639f3f32cb15c8ff0dc3997c4549f51a"}, + {file = "cryptography-41.0.5-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:da6a0ff8f1016ccc7477e6339e1d50ce5f59b88905585f77193ebd5068f1e797"}, + {file = "cryptography-41.0.5-cp37-abi3-macosx_10_12_x86_64.whl", hash = "sha256:b948e09fe5fb18517d99994184854ebd50b57248736fd4c720ad540560174ec5"}, + {file = "cryptography-41.0.5-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d38e6031e113b7421db1de0c1b1f7739564a88f1684c6b89234fbf6c11b75147"}, + {file = "cryptography-41.0.5-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e270c04f4d9b5671ebcc792b3ba5d4488bf7c42c3c241a3748e2599776f29696"}, + {file = "cryptography-41.0.5-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:ec3b055ff8f1dce8e6ef28f626e0972981475173d7973d63f271b29c8a2897da"}, + {file = "cryptography-41.0.5-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:7d208c21e47940369accfc9e85f0de7693d9a5d843c2509b3846b2db170dfd20"}, + {file = "cryptography-41.0.5-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:8254962e6ba1f4d2090c44daf50a547cd5f0bf446dc658a8e5f8156cae0d8548"}, + {file = "cryptography-41.0.5-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:a48e74dad1fb349f3dc1d449ed88e0017d792997a7ad2ec9587ed17405667e6d"}, + {file = "cryptography-41.0.5-cp37-abi3-win32.whl", hash = "sha256:d3977f0e276f6f5bf245c403156673db103283266601405376f075c849a0b936"}, + {file = "cryptography-41.0.5-cp37-abi3-win_amd64.whl", hash = "sha256:73801ac9736741f220e20435f84ecec75ed70eda90f781a148f1bad546963d81"}, + {file = "cryptography-41.0.5-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:3be3ca726e1572517d2bef99a818378bbcf7d7799d5372a46c79c29eb8d166c1"}, + {file = "cryptography-41.0.5-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:e886098619d3815e0ad5790c973afeee2c0e6e04b4da90b88e6bd06e2a0b1b72"}, + {file = "cryptography-41.0.5-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:573eb7128cbca75f9157dcde974781209463ce56b5804983e11a1c462f0f4e88"}, + {file = "cryptography-41.0.5-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:0c327cac00f082013c7c9fb6c46b7cc9fa3c288ca702c74773968173bda421bf"}, + {file = "cryptography-41.0.5-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:227ec057cd32a41c6651701abc0328135e472ed450f47c2766f23267b792a88e"}, + {file = "cryptography-41.0.5-pp38-pypy38_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:22892cc830d8b2c89ea60148227631bb96a7da0c1b722f2aac8824b1b7c0b6b8"}, + {file = "cryptography-41.0.5-pp38-pypy38_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:5a70187954ba7292c7876734183e810b728b4f3965fbe571421cb2434d279179"}, + {file = "cryptography-41.0.5-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:88417bff20162f635f24f849ab182b092697922088b477a7abd6664ddd82291d"}, + {file = "cryptography-41.0.5-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:c707f7afd813478e2019ae32a7c49cd932dd60ab2d2a93e796f68236b7e1fbf1"}, + {file = "cryptography-41.0.5-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:580afc7b7216deeb87a098ef0674d6ee34ab55993140838b14c9b83312b37b86"}, + {file = "cryptography-41.0.5-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:fba1e91467c65fe64a82c689dc6cf58151158993b13eb7a7f3f4b7f395636723"}, + {file = "cryptography-41.0.5-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:0d2a6a598847c46e3e321a7aef8af1436f11c27f1254933746304ff014664d84"}, + {file = "cryptography-41.0.5.tar.gz", hash = "sha256:392cb88b597247177172e02da6b7a63deeff1937fa6fec3bbf902ebd75d97ec7"}, ] [package.dependencies] @@ -856,13 +856,13 @@ test = ["pytest (>=6)"] [[package]] name = "executing" -version = "2.0.0" +version = "2.0.1" description = "Get the currently executing AST node of a frame, and other information" optional = false -python-versions = "*" +python-versions = ">=3.5" files = [ - {file = "executing-2.0.0-py2.py3-none-any.whl", hash = "sha256:06df6183df67389625f4e763921c6cf978944721abf3e714000200aab95b0657"}, - {file = "executing-2.0.0.tar.gz", hash = "sha256:0ff053696fdeef426cda5bd18eacd94f82c91f49823a2e9090124212ceea9b08"}, + {file = "executing-2.0.1-py2.py3-none-any.whl", hash = "sha256:eac49ca94516ccc753f9fb5ce82603156e590b27525a8bc32cce8ae302eb61bc"}, + {file = "executing-2.0.1.tar.gz", hash = "sha256:35afe2ce3affba8ee97f2d69927fa823b08b472b7b994e36a52a964b93d16147"}, ] [package.extras] @@ -980,13 +980,13 @@ testing = ["flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pyfakefs [[package]] name = "importlib-resources" -version = "6.1.0" +version = "6.1.1" description = "Read resources from Python packages" optional = false python-versions = ">=3.8" files = [ - {file = "importlib_resources-6.1.0-py3-none-any.whl", hash = "sha256:aa50258bbfa56d4e33fbd8aa3ef48ded10d1735f11532b8df95388cc6bdb7e83"}, - {file = "importlib_resources-6.1.0.tar.gz", hash = "sha256:9d48dcccc213325e810fd723e7fbb45ccb39f6cf5c31f00cf2b965f5f10f3cb9"}, + {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] @@ -1009,13 +1009,13 @@ files = [ [[package]] name = "ipykernel" -version = "6.25.2" +version = "6.26.0" description = "IPython Kernel for Jupyter" optional = false python-versions = ">=3.8" files = [ - {file = "ipykernel-6.25.2-py3-none-any.whl", hash = "sha256:2e2ee359baba19f10251b99415bb39de1e97d04e1fab385646f24f0596510b77"}, - {file = "ipykernel-6.25.2.tar.gz", hash = "sha256:f468ddd1f17acb48c8ce67fcfa49ba6d46d4f9ac0438c1f441be7c3d1372230b"}, + {file = "ipykernel-6.26.0-py3-none-any.whl", hash = "sha256:3ba3dc97424b87b31bb46586b5167b3161b32d7820b9201a9e698c71e271602c"}, + {file = "ipykernel-6.26.0.tar.gz", hash = "sha256:553856658eb8430bbe9653ea041a41bff63e9606fc4628873fc92a6cf3abd404"}, ] [package.dependencies] @@ -1081,25 +1081,23 @@ test-extra = ["curio", "matplotlib (!=3.2.0)", "nbformat", "numpy (>=1.21)", "pa [[package]] name = "ipython" -version = "8.16.1" +version = "8.17.2" description = "IPython: Productive Interactive Computing" optional = false python-versions = ">=3.9" files = [ - {file = "ipython-8.16.1-py3-none-any.whl", hash = "sha256:0852469d4d579d9cd613c220af7bf0c9cc251813e12be647cb9d463939db9b1e"}, - {file = "ipython-8.16.1.tar.gz", hash = "sha256:ad52f58fca8f9f848e256c629eff888efc0528c12fe0f8ec14f33205f23ef938"}, + {file = "ipython-8.17.2-py3-none-any.whl", hash = "sha256:1e4d1d666a023e3c93585ba0d8e962867f7a111af322efff6b9c58062b3e5444"}, + {file = "ipython-8.17.2.tar.gz", hash = "sha256:126bb57e1895594bb0d91ea3090bbd39384f6fe87c3d57fd558d0670f50339bb"}, ] [package.dependencies] appnope = {version = "*", markers = "sys_platform == \"darwin\""} -backcall = "*" colorama = {version = "*", markers = "sys_platform == \"win32\""} decorator = "*" exceptiongroup = {version = "*", markers = "python_version < \"3.11\""} jedi = ">=0.16" matplotlib-inline = "*" pexpect = {version = ">4.3", markers = "sys_platform != \"win32\""} -pickleshare = "*" prompt-toolkit = ">=3.0.30,<3.0.37 || >3.0.37,<3.1.0" pygments = ">=2.4.0" stack-data = "*" @@ -1107,17 +1105,17 @@ traitlets = ">=5" typing-extensions = {version = "*", markers = "python_version < \"3.10\""} [package.extras] -all = ["black", "curio", "docrepr", "exceptiongroup", "ipykernel", "ipyparallel", "ipywidgets", "matplotlib", "matplotlib (!=3.2.0)", "nbconvert", "nbformat", "notebook", "numpy (>=1.21)", "pandas", "pytest (<7)", "pytest (<7.1)", "pytest-asyncio", "qtconsole", "setuptools (>=18.5)", "sphinx (>=1.3)", "sphinx-rtd-theme", "stack-data", "testpath", "trio", "typing-extensions"] +all = ["black", "curio", "docrepr", "exceptiongroup", "ipykernel", "ipyparallel", "ipywidgets", "matplotlib", "matplotlib (!=3.2.0)", "nbconvert", "nbformat", "notebook", "numpy (>=1.22)", "pandas", "pickleshare", "pytest (<7)", "pytest (<7.1)", "pytest-asyncio (<0.22)", "qtconsole", "setuptools (>=18.5)", "sphinx (>=1.3)", "sphinx-rtd-theme", "stack-data", "testpath", "trio", "typing-extensions"] black = ["black"] -doc = ["docrepr", "exceptiongroup", "ipykernel", "matplotlib", "pytest (<7)", "pytest (<7.1)", "pytest-asyncio", "setuptools (>=18.5)", "sphinx (>=1.3)", "sphinx-rtd-theme", "stack-data", "testpath", "typing-extensions"] +doc = ["docrepr", "exceptiongroup", "ipykernel", "matplotlib", "pickleshare", "pytest (<7)", "pytest (<7.1)", "pytest-asyncio (<0.22)", "setuptools (>=18.5)", "sphinx (>=1.3)", "sphinx-rtd-theme", "stack-data", "testpath", "typing-extensions"] kernel = ["ipykernel"] nbconvert = ["nbconvert"] nbformat = ["nbformat"] notebook = ["ipywidgets", "notebook"] parallel = ["ipyparallel"] qtconsole = ["qtconsole"] -test = ["pytest (<7.1)", "pytest-asyncio", "testpath"] -test-extra = ["curio", "matplotlib (!=3.2.0)", "nbformat", "numpy (>=1.21)", "pandas", "pytest (<7.1)", "pytest-asyncio", "testpath", "trio"] +test = ["pickleshare", "pytest (<7.1)", "pytest-asyncio (<0.22)", "testpath"] +test-extra = ["curio", "matplotlib (!=3.2.0)", "nbformat", "numpy (>=1.22)", "pandas", "pickleshare", "pytest (<7.1)", "pytest-asyncio (<0.22)", "testpath", "trio"] [[package]] name = "isoduration" @@ -1195,13 +1193,13 @@ files = [ [[package]] name = "jsonschema" -version = "4.19.1" +version = "4.19.2" description = "An implementation of JSON Schema validation for Python" optional = false python-versions = ">=3.8" files = [ - {file = "jsonschema-4.19.1-py3-none-any.whl", hash = "sha256:cd5f1f9ed9444e554b38ba003af06c0a8c2868131e56bfbef0550fb450c0330e"}, - {file = "jsonschema-4.19.1.tar.gz", hash = "sha256:ec84cc37cfa703ef7cd4928db24f9cb31428a5d0fa77747b8b51a847458e0bbf"}, + {file = "jsonschema-4.19.2-py3-none-any.whl", hash = "sha256:eee9e502c788e89cb166d4d37f43084e3b64ab405c795c03d343a4dbc2c810fc"}, + {file = "jsonschema-4.19.2.tar.gz", hash = "sha256:c9ff4d7447eed9592c23a12ccee508baf0dd0d59650615e847feb6cdca74f392"}, ] [package.dependencies] @@ -1241,13 +1239,13 @@ referencing = ">=0.28.0" [[package]] name = "jupyter-client" -version = "8.4.0" +version = "8.6.0" description = "Jupyter protocol implementation and client libraries" optional = false python-versions = ">=3.8" files = [ - {file = "jupyter_client-8.4.0-py3-none-any.whl", hash = "sha256:6a2a950ec23a8f62f9e4c66acec7f0ea6c7d1f80ba0992e747b10c56ce2e6dbe"}, - {file = "jupyter_client-8.4.0.tar.gz", hash = "sha256:dc1b857d5d7d76ac101766c6e9b646bf18742721126e72e5d484c75a993cada2"}, + {file = "jupyter_client-8.6.0-py3-none-any.whl", hash = "sha256:909c474dbe62582ae62b758bca86d6518c85234bdee2d908c778db6d72f39d99"}, + {file = "jupyter_client-8.6.0.tar.gz", hash = "sha256:0642244bb83b4764ae60d07e010e15f0e2d275ec4e918a8f7b80fbbef3ca60c7"}, ] [package.dependencies] @@ -1264,13 +1262,13 @@ test = ["coverage", "ipykernel (>=6.14)", "mypy", "paramiko", "pre-commit", "pyt [[package]] name = "jupyter-core" -version = "5.4.0" +version = "5.5.0" description = "Jupyter core package. A base package on which Jupyter projects rely." optional = false python-versions = ">=3.8" files = [ - {file = "jupyter_core-5.4.0-py3-none-any.whl", hash = "sha256:66e252f675ac04dcf2feb6ed4afb3cd7f68cf92f483607522dc251f32d471571"}, - {file = "jupyter_core-5.4.0.tar.gz", hash = "sha256:e4b98344bb94ee2e3e6c4519a97d001656009f9cb2b7f2baf15b3c205770011d"}, + {file = "jupyter_core-5.5.0-py3-none-any.whl", hash = "sha256:e11e02cd8ae0a9de5c6c44abf5727df9f2581055afe00b22183f621ba3585805"}, + {file = "jupyter_core-5.5.0.tar.gz", hash = "sha256:880b86053bf298a8724994f95e99b99130659022a4f7f45f563084b6223861d3"}, ] [package.dependencies] @@ -1279,18 +1277,18 @@ pywin32 = {version = ">=300", markers = "sys_platform == \"win32\" and platform_ traitlets = ">=5.3" [package.extras] -docs = ["myst-parser", "sphinx-autodoc-typehints", "sphinxcontrib-github-alt", "sphinxcontrib-spelling", "traitlets"] +docs = ["myst-parser", "pydata-sphinx-theme", "sphinx-autodoc-typehints", "sphinxcontrib-github-alt", "sphinxcontrib-spelling", "traitlets"] test = ["ipykernel", "pre-commit", "pytest", "pytest-cov", "pytest-timeout"] [[package]] name = "jupyter-events" -version = "0.8.0" +version = "0.9.0" description = "Jupyter Event System library" optional = false python-versions = ">=3.8" files = [ - {file = "jupyter_events-0.8.0-py3-none-any.whl", hash = "sha256:81f07375c7673ff298bfb9302b4a981864ec64edaed75ca0fe6f850b9b045525"}, - {file = "jupyter_events-0.8.0.tar.gz", hash = "sha256:fda08f0defce5e16930542ce60634ba48e010830d50073c3dfd235759cee77bf"}, + {file = "jupyter_events-0.9.0-py3-none-any.whl", hash = "sha256:d853b3c10273ff9bc8bb8b30076d65e2c9685579db736873de6c2232dde148bf"}, + {file = "jupyter_events-0.9.0.tar.gz", hash = "sha256:81ad2e4bc710881ec274d31c6c50669d71bbaa5dd9d01e600b56faa85700d399"}, ] [package.dependencies] @@ -1324,13 +1322,13 @@ jupyter-server = ">=1.1.2" [[package]] name = "jupyter-server" -version = "2.8.0" +version = "2.10.0" description = "The backend—i.e. core services, APIs, and REST endpoints—to Jupyter web applications." optional = false python-versions = ">=3.8" files = [ - {file = "jupyter_server-2.8.0-py3-none-any.whl", hash = "sha256:c57270faa6530393ae69783a2d2f1874c718b9f109080581ea076b05713249fa"}, - {file = "jupyter_server-2.8.0.tar.gz", hash = "sha256:b11e2ba80667c75f55630faf8ac3d5809f8734f9006d65cce117c46a0a516ab8"}, + {file = "jupyter_server-2.10.0-py3-none-any.whl", hash = "sha256:dde56c9bc3cb52d7b72cc0f696d15d7163603526f1a758eb4a27405b73eab2a5"}, + {file = "jupyter_server-2.10.0.tar.gz", hash = "sha256:47b8f5e63440125cb1bb8957bf12b18453ee5ed9efe42d2f7b2ca66a7019a278"}, ] [package.dependencies] @@ -1379,13 +1377,13 @@ test = ["coverage", "jupyter-server (>=2.0.0)", "pytest (>=7.0)", "pytest-cov", [[package]] name = "jupyterlab" -version = "4.0.7" +version = "4.0.8" description = "JupyterLab computational environment" optional = false python-versions = ">=3.8" files = [ - {file = "jupyterlab-4.0.7-py3-none-any.whl", hash = "sha256:08683045117cc495531fdb39c22ababb9aaac6977a45e67cfad20046564c9c7c"}, - {file = "jupyterlab-4.0.7.tar.gz", hash = "sha256:48792efd9f962b2bcda1f87d72168ff122c288b1d97d32109e4a11b33dc862be"}, + {file = "jupyterlab-4.0.8-py3-none-any.whl", hash = "sha256:2ff5aa2a51eb21df241d6011c236e88bd1ff9a5dbb75bebc54472f9c18bfffa4"}, + {file = "jupyterlab-4.0.8.tar.gz", hash = "sha256:c4fe93f977bcc987bd395d7fae5ab02e0c042bf4e0f7c95196f3e2e578c2fb3a"}, ] [package.dependencies] @@ -1405,7 +1403,7 @@ tornado = ">=6.2.0" traitlets = "*" [package.extras] -dev = ["black[jupyter] (==23.7.0)", "build", "bump2version", "coverage", "hatch", "pre-commit", "pytest-cov", "ruff (==0.0.286)"] +dev = ["black[jupyter] (==23.10.1)", "build", "bump2version", "coverage", "hatch", "pre-commit", "pytest-cov", "ruff (==0.0.292)"] docs = ["jsx-lexer", "myst-parser", "pydata-sphinx-theme (>=0.13.0)", "pytest", "pytest-check-links", "pytest-tornasync", "sphinx (>=1.8,<7.2.0)", "sphinx-copybutton"] docs-screenshots = ["altair (==5.0.1)", "ipython (==8.14.0)", "ipywidgets (==8.0.6)", "jupyterlab-geojson (==3.4.0)", "jupyterlab-language-pack-zh-cn (==4.0.post0)", "matplotlib (==3.7.1)", "nbconvert (>=7.0.0)", "pandas (==2.0.2)", "scipy (==1.10.1)", "vega-datasets (==0.9.0)"] test = ["coverage", "pytest (>=7.0)", "pytest-check-links (>=0.7)", "pytest-console-scripts", "pytest-cov", "pytest-jupyter (>=0.5.3)", "pytest-timeout", "pytest-tornasync", "requests", "requests-cache", "virtualenv"] @@ -1423,13 +1421,13 @@ files = [ [[package]] name = "jupyterlab-server" -version = "2.25.0" +version = "2.25.1" description = "A set of server components for JupyterLab and JupyterLab like applications." optional = false python-versions = ">=3.8" files = [ - {file = "jupyterlab_server-2.25.0-py3-none-any.whl", hash = "sha256:c9f67a98b295c5dee87f41551b0558374e45d449f3edca153dd722140630dcb2"}, - {file = "jupyterlab_server-2.25.0.tar.gz", hash = "sha256:77c2f1f282d610f95e496e20d5bf1d2a7706826dfb7b18f3378ae2870d272fb7"}, + {file = "jupyterlab_server-2.25.1-py3-none-any.whl", hash = "sha256:dce9714d91fb3e53d2b37d0e0619fa26ed223c8e7b8c81cca112926de19b53a4"}, + {file = "jupyterlab_server-2.25.1.tar.gz", hash = "sha256:6491283b0000698eae1a38c48507930560dfcf7461aea0015368698aab34dd9c"}, ] [package.dependencies] @@ -1445,7 +1443,7 @@ requests = ">=2.31" [package.extras] docs = ["autodoc-traits", "jinja2 (<3.2.0)", "mistune (<4)", "myst-parser", "pydata-sphinx-theme", "sphinx", "sphinx-copybutton", "sphinxcontrib-openapi (>0.8)"] openapi = ["openapi-core (>=0.18.0,<0.19.0)", "ruamel-yaml"] -test = ["hatch", "ipykernel", "openapi-core (>=0.18.0,<0.19.0)", "openapi-spec-validator (>=0.6.0,<0.7.0)", "pytest (>=7.0)", "pytest-console-scripts", "pytest-cov", "pytest-jupyter[server] (>=0.6.2)", "pytest-timeout", "requests-mock", "ruamel-yaml", "sphinxcontrib-spelling", "strict-rfc3339", "werkzeug"] +test = ["hatch", "ipykernel", "openapi-core (>=0.18.0,<0.19.0)", "openapi-spec-validator (>=0.6.0,<0.8.0)", "pytest (>=7.0)", "pytest-console-scripts", "pytest-cov", "pytest-jupyter[server] (>=0.6.2)", "pytest-timeout", "requests-mock", "ruamel-yaml", "sphinxcontrib-spelling", "strict-rfc3339", "werkzeug"] [[package]] name = "lark" @@ -1596,38 +1594,38 @@ olefile = ">=0.46" [[package]] name = "mypy" -version = "1.6.1" +version = "1.7.0" description = "Optional static typing for Python" optional = false python-versions = ">=3.8" files = [ - {file = "mypy-1.6.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e5012e5cc2ac628177eaac0e83d622b2dd499e28253d4107a08ecc59ede3fc2c"}, - {file = "mypy-1.6.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d8fbb68711905f8912e5af474ca8b78d077447d8f3918997fecbf26943ff3cbb"}, - {file = "mypy-1.6.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21a1ad938fee7d2d96ca666c77b7c494c3c5bd88dff792220e1afbebb2925b5e"}, - {file = "mypy-1.6.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:b96ae2c1279d1065413965c607712006205a9ac541895004a1e0d4f281f2ff9f"}, - {file = "mypy-1.6.1-cp310-cp310-win_amd64.whl", hash = "sha256:40b1844d2e8b232ed92e50a4bd11c48d2daa351f9deee6c194b83bf03e418b0c"}, - {file = "mypy-1.6.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:81af8adaa5e3099469e7623436881eff6b3b06db5ef75e6f5b6d4871263547e5"}, - {file = "mypy-1.6.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:8c223fa57cb154c7eab5156856c231c3f5eace1e0bed9b32a24696b7ba3c3245"}, - {file = "mypy-1.6.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a8032e00ce71c3ceb93eeba63963b864bf635a18f6c0c12da6c13c450eedb183"}, - {file = "mypy-1.6.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:4c46b51de523817a0045b150ed11b56f9fff55f12b9edd0f3ed35b15a2809de0"}, - {file = "mypy-1.6.1-cp311-cp311-win_amd64.whl", hash = "sha256:19f905bcfd9e167159b3d63ecd8cb5e696151c3e59a1742e79bc3bcb540c42c7"}, - {file = "mypy-1.6.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:82e469518d3e9a321912955cc702d418773a2fd1e91c651280a1bda10622f02f"}, - {file = "mypy-1.6.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d4473c22cc296425bbbce7e9429588e76e05bc7342da359d6520b6427bf76660"}, - {file = "mypy-1.6.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:59a0d7d24dfb26729e0a068639a6ce3500e31d6655df8557156c51c1cb874ce7"}, - {file = "mypy-1.6.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:cfd13d47b29ed3bbaafaff7d8b21e90d827631afda134836962011acb5904b71"}, - {file = "mypy-1.6.1-cp312-cp312-win_amd64.whl", hash = "sha256:eb4f18589d196a4cbe5290b435d135dee96567e07c2b2d43b5c4621b6501531a"}, - {file = "mypy-1.6.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:41697773aa0bf53ff917aa077e2cde7aa50254f28750f9b88884acea38a16169"}, - {file = "mypy-1.6.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7274b0c57737bd3476d2229c6389b2ec9eefeb090bbaf77777e9d6b1b5a9d143"}, - {file = "mypy-1.6.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bbaf4662e498c8c2e352da5f5bca5ab29d378895fa2d980630656178bd607c46"}, - {file = "mypy-1.6.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:bb8ccb4724f7d8601938571bf3f24da0da791fe2db7be3d9e79849cb64e0ae85"}, - {file = "mypy-1.6.1-cp38-cp38-win_amd64.whl", hash = "sha256:68351911e85145f582b5aa6cd9ad666c8958bcae897a1bfda8f4940472463c45"}, - {file = "mypy-1.6.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:49ae115da099dcc0922a7a895c1eec82c1518109ea5c162ed50e3b3594c71208"}, - {file = "mypy-1.6.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:8b27958f8c76bed8edaa63da0739d76e4e9ad4ed325c814f9b3851425582a3cd"}, - {file = "mypy-1.6.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:925cd6a3b7b55dfba252b7c4561892311c5358c6b5a601847015a1ad4eb7d332"}, - {file = "mypy-1.6.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8f57e6b6927a49550da3d122f0cb983d400f843a8a82e65b3b380d3d7259468f"}, - {file = "mypy-1.6.1-cp39-cp39-win_amd64.whl", hash = "sha256:a43ef1c8ddfdb9575691720b6352761f3f53d85f1b57d7745701041053deff30"}, - {file = "mypy-1.6.1-py3-none-any.whl", hash = "sha256:4cbe68ef919c28ea561165206a2dcb68591c50f3bcf777932323bc208d949cf1"}, - {file = "mypy-1.6.1.tar.gz", hash = "sha256:4d01c00d09a0be62a4ca3f933e315455bde83f37f892ba4b08ce92f3cf44bcc1"}, + {file = "mypy-1.7.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5da84d7bf257fd8f66b4f759a904fd2c5a765f70d8b52dde62b521972a0a2357"}, + {file = "mypy-1.7.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a3637c03f4025f6405737570d6cbfa4f1400eb3c649317634d273687a09ffc2f"}, + {file = "mypy-1.7.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b633f188fc5ae1b6edca39dae566974d7ef4e9aaaae00bc36efe1f855e5173ac"}, + {file = "mypy-1.7.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:d6ed9a3997b90c6f891138e3f83fb8f475c74db4ccaa942a1c7bf99e83a989a1"}, + {file = "mypy-1.7.0-cp310-cp310-win_amd64.whl", hash = "sha256:1fe46e96ae319df21359c8db77e1aecac8e5949da4773c0274c0ef3d8d1268a9"}, + {file = "mypy-1.7.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:df67fbeb666ee8828f675fee724cc2cbd2e4828cc3df56703e02fe6a421b7401"}, + {file = "mypy-1.7.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a79cdc12a02eb526d808a32a934c6fe6df07b05f3573d210e41808020aed8b5d"}, + {file = "mypy-1.7.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f65f385a6f43211effe8c682e8ec3f55d79391f70a201575def73d08db68ead1"}, + {file = "mypy-1.7.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:0e81ffd120ee24959b449b647c4b2fbfcf8acf3465e082b8d58fd6c4c2b27e46"}, + {file = "mypy-1.7.0-cp311-cp311-win_amd64.whl", hash = "sha256:f29386804c3577c83d76520abf18cfcd7d68264c7e431c5907d250ab502658ee"}, + {file = "mypy-1.7.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:87c076c174e2c7ef8ab416c4e252d94c08cd4980a10967754f91571070bf5fbe"}, + {file = "mypy-1.7.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6cb8d5f6d0fcd9e708bb190b224089e45902cacef6f6915481806b0c77f7786d"}, + {file = "mypy-1.7.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d93e76c2256aa50d9c82a88e2f569232e9862c9982095f6d54e13509f01222fc"}, + {file = "mypy-1.7.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:cddee95dea7990e2215576fae95f6b78a8c12f4c089d7e4367564704e99118d3"}, + {file = "mypy-1.7.0-cp312-cp312-win_amd64.whl", hash = "sha256:d01921dbd691c4061a3e2ecdbfbfad029410c5c2b1ee88946bf45c62c6c91210"}, + {file = "mypy-1.7.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:185cff9b9a7fec1f9f7d8352dff8a4c713b2e3eea9c6c4b5ff7f0edf46b91e41"}, + {file = "mypy-1.7.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7a7b1e399c47b18feb6f8ad4a3eef3813e28c1e871ea7d4ea5d444b2ac03c418"}, + {file = "mypy-1.7.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc9fe455ad58a20ec68599139ed1113b21f977b536a91b42bef3ffed5cce7391"}, + {file = "mypy-1.7.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:d0fa29919d2e720c8dbaf07d5578f93d7b313c3e9954c8ec05b6d83da592e5d9"}, + {file = "mypy-1.7.0-cp38-cp38-win_amd64.whl", hash = "sha256:2b53655a295c1ed1af9e96b462a736bf083adba7b314ae775563e3fb4e6795f5"}, + {file = "mypy-1.7.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c1b06b4b109e342f7dccc9efda965fc3970a604db70f8560ddfdee7ef19afb05"}, + {file = "mypy-1.7.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:bf7a2f0a6907f231d5e41adba1a82d7d88cf1f61a70335889412dec99feeb0f8"}, + {file = "mypy-1.7.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:551d4a0cdcbd1d2cccdcc7cb516bb4ae888794929f5b040bb51aae1846062901"}, + {file = "mypy-1.7.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:55d28d7963bef00c330cb6461db80b0b72afe2f3c4e2963c99517cf06454e665"}, + {file = "mypy-1.7.0-cp39-cp39-win_amd64.whl", hash = "sha256:870bd1ffc8a5862e593185a4c169804f2744112b4a7c55b93eb50f48e7a77010"}, + {file = "mypy-1.7.0-py3-none-any.whl", hash = "sha256:96650d9a4c651bc2a4991cf46f100973f656d69edc7faf91844e87fe627f7e96"}, + {file = "mypy-1.7.0.tar.gz", hash = "sha256:1e280b5697202efa698372d2f39e9a6713a0395a756b1c6bd48995f8d72690dc"}, ] [package.dependencies] @@ -1638,6 +1636,7 @@ typing-extensions = ">=4.1.0" [package.extras] dmypy = ["psutil (>=4.0)"] install-types = ["pip"] +mypyc = ["setuptools (>=50)"] reports = ["lxml"] [[package]] @@ -1653,13 +1652,13 @@ files = [ [[package]] name = "nbclient" -version = "0.8.0" +version = "0.9.0" description = "A client library for executing notebooks. Formerly nbconvert's ExecutePreprocessor." optional = false python-versions = ">=3.8.0" files = [ - {file = "nbclient-0.8.0-py3-none-any.whl", hash = "sha256:25e861299e5303a0477568557c4045eccc7a34c17fc08e7959558707b9ebe548"}, - {file = "nbclient-0.8.0.tar.gz", hash = "sha256:f9b179cd4b2d7bca965f900a2ebf0db4a12ebff2f36a711cb66861e4ae158e55"}, + {file = "nbclient-0.9.0-py3-none-any.whl", hash = "sha256:a3a1ddfb34d4a9d17fc744d655962714a866639acd30130e9be84191cd97cd15"}, + {file = "nbclient-0.9.0.tar.gz", hash = "sha256:4b28c207877cf33ef3a9838cdc7a54c5ceff981194a82eac59d558f05487295e"}, ] [package.dependencies] @@ -1675,13 +1674,13 @@ test = ["flaky", "ipykernel (>=6.19.3)", "ipython", "ipywidgets", "nbconvert (>= [[package]] name = "nbconvert" -version = "7.9.2" +version = "7.11.0" description = "Converting Jupyter Notebooks" optional = false python-versions = ">=3.8" files = [ - {file = "nbconvert-7.9.2-py3-none-any.whl", hash = "sha256:39fe4b8bdd1b0104fdd86fc8a43a9077ba64c720bda4c6132690d917a0a154ee"}, - {file = "nbconvert-7.9.2.tar.gz", hash = "sha256:e56cc7588acc4f93e2bb5a34ec69028e4941797b2bfaf6462f18a41d1cc258c9"}, + {file = "nbconvert-7.11.0-py3-none-any.whl", hash = "sha256:d1d417b7f34a4e38887f8da5bdfd12372adf3b80f995d57556cb0972c68909fe"}, + {file = "nbconvert-7.11.0.tar.gz", hash = "sha256:abedc01cf543177ffde0bfc2a69726d5a478f6af10a332fc1bf29fcb4f0cf000"}, ] [package.dependencies] @@ -1708,7 +1707,7 @@ docs = ["ipykernel", "ipython", "myst-parser", "nbsphinx (>=0.2.12)", "pydata-sp qtpdf = ["nbconvert[qtpng]"] qtpng = ["pyqtwebengine (>=5.15)"] serve = ["tornado (>=6.1)"] -test = ["flaky", "ipykernel", "ipywidgets (>=7)", "pytest", "pytest-dependency"] +test = ["flaky", "ipykernel", "ipywidgets (>=7)", "pytest"] webpdf = ["playwright"] [[package]] @@ -1960,13 +1959,13 @@ files = [ [[package]] name = "platformdirs" -version = "3.11.0" +version = "4.0.0" description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." optional = false python-versions = ">=3.7" files = [ - {file = "platformdirs-3.11.0-py3-none-any.whl", hash = "sha256:e9d171d00af68be50e9202731309c4e658fd8bc76f55c11c7dd760d023bda68e"}, - {file = "platformdirs-3.11.0.tar.gz", hash = "sha256:cf8ee52a3afdb965072dcc652433e0c7e3e40cf5ea1477cd4b3b1d2eb75495b3"}, + {file = "platformdirs-4.0.0-py3-none-any.whl", hash = "sha256:118c954d7e949b35437270383a3f2531e99dd93cf7ce4dc8340d3356d30f173b"}, + {file = "platformdirs-4.0.0.tar.gz", hash = "sha256:cb633b2bcf10c51af60beb0ab06d2f1d69064b43abf4c185ca6b28865f3f9731"}, ] [package.extras] @@ -1990,13 +1989,13 @@ testing = ["pytest", "pytest-benchmark"] [[package]] name = "prometheus-client" -version = "0.17.1" +version = "0.18.0" description = "Python client for the Prometheus monitoring system." optional = false -python-versions = ">=3.6" +python-versions = ">=3.8" files = [ - {file = "prometheus_client-0.17.1-py3-none-any.whl", hash = "sha256:e537f37160f6807b8202a6fc4764cdd19bac5480ddd3e0d463c3002b34462101"}, - {file = "prometheus_client-0.17.1.tar.gz", hash = "sha256:21e674f39831ae3f8acde238afd9a27a37d0d2fb5a28ea094f0ce25d2cbf2091"}, + {file = "prometheus_client-0.18.0-py3-none-any.whl", hash = "sha256:8de3ae2755f890826f4b6479e5571d4f74ac17a81345fe69a6778fdb92579184"}, + {file = "prometheus_client-0.18.0.tar.gz", hash = "sha256:35f7a8c22139e2bb7ca5a698e92d38145bc8dc74c1c0bf56f25cca886a764e17"}, ] [package.extras] @@ -2004,13 +2003,13 @@ twisted = ["twisted"] [[package]] name = "prompt-toolkit" -version = "3.0.39" +version = "3.0.41" description = "Library for building powerful interactive command lines in Python" optional = false python-versions = ">=3.7.0" files = [ - {file = "prompt_toolkit-3.0.39-py3-none-any.whl", hash = "sha256:9dffbe1d8acf91e3de75f3b544e4842382fc06c6babe903ac9acb74dc6e08d88"}, - {file = "prompt_toolkit-3.0.39.tar.gz", hash = "sha256:04505ade687dc26dc4284b1ad19a83be2f2afe83e7a828ace0c72f3a1df72aac"}, + {file = "prompt_toolkit-3.0.41-py3-none-any.whl", hash = "sha256:f36fe301fafb7470e86aaf90f036eef600a3210be4decf461a5b1ca8403d3cb2"}, + {file = "prompt_toolkit-3.0.41.tar.gz", hash = "sha256:941367d97fc815548822aa26c2a269fdc4eb21e9ec05fc5d447cf09bad5d75f0"}, ] [package.dependencies] @@ -2057,13 +2056,13 @@ files = [ [[package]] name = "publicsuffixlist" -version = "0.10.0.20231022" +version = "0.10.0.20231109" description = "publicsuffixlist implement" optional = true python-versions = ">=2.6" files = [ - {file = "publicsuffixlist-0.10.0.20231022-py2.py3-none-any.whl", hash = "sha256:97eb6e2f87d3ea913144ef218ea1851fe3e3241a7b2f0c84ac0b61d87816e2aa"}, - {file = "publicsuffixlist-0.10.0.20231022.tar.gz", hash = "sha256:b179a7b6e92be26f3beb1e07bb8e6d1e54f4d6b236f25ed84f9f6ed935bc4d5e"}, + {file = "publicsuffixlist-0.10.0.20231109-py2.py3-none-any.whl", hash = "sha256:72888d1a5da95b78345bc8b228125c1e32896109efda1947d8df92a62cc325cd"}, + {file = "publicsuffixlist-0.10.0.20231109.tar.gz", hash = "sha256:72bdab12819527c05e5cb7f23eae00bb1bbb3843a55672b19523144449a38b61"}, ] [package.extras] @@ -2155,13 +2154,13 @@ files = [ [[package]] name = "pytest" -version = "7.4.2" +version = "7.4.3" description = "pytest: simple powerful testing with Python" optional = false python-versions = ">=3.7" files = [ - {file = "pytest-7.4.2-py3-none-any.whl", hash = "sha256:1d881c6124e08ff0a1bb75ba3ec0bfd8b5354a01c194ddd5a0a870a48d99b002"}, - {file = "pytest-7.4.2.tar.gz", hash = "sha256:a766259cfab564a2ad52cb1aae1b881a75c3eb7e34ca3779697c23ed47c47069"}, + {file = "pytest-7.4.3-py3-none-any.whl", hash = "sha256:0d009c083ea859a71b76adf7c1d502e4bc170b80a8ef002da5806527b9591fac"}, + {file = "pytest-7.4.3.tar.gz", hash = "sha256:d989d136982de4e3b29dabcc838ad581c64e8ed52c11fbe86ddebd9da0818cd5"}, ] [package.dependencies] @@ -2475,13 +2474,13 @@ rpds-py = ">=0.7.0" [[package]] name = "reportlab" -version = "4.0.6" +version = "4.0.7" description = "The Reportlab Toolkit" optional = true python-versions = ">=3.7,<4" files = [ - {file = "reportlab-4.0.6-py3-none-any.whl", hash = "sha256:ec062675202eb76f6100ed44da64f38ed3c7feb5016cf4fe7f17ce35423ab14a"}, - {file = "reportlab-4.0.6.tar.gz", hash = "sha256:069aa35da7c882921f419f6e26327e14dac1d9d0adeb40b584cdadd974d99fc0"}, + {file = "reportlab-4.0.7-py3-none-any.whl", hash = "sha256:956d5874ee56e88753cf4c49452d6a7fa54a64e049a0382bd0c0b2013a26ef9a"}, + {file = "reportlab-4.0.7.tar.gz", hash = "sha256:967c77f00efd918cc231cf8b6d8f4e477dc973b5c16557e3bd18dfaeb5a70234"}, ] [package.dependencies] @@ -2559,110 +2558,110 @@ files = [ [[package]] name = "rpds-py" -version = "0.10.6" +version = "0.12.0" description = "Python bindings to Rust's persistent data structures (rpds)" optional = false python-versions = ">=3.8" files = [ - {file = "rpds_py-0.10.6-cp310-cp310-macosx_10_7_x86_64.whl", hash = "sha256:6bdc11f9623870d75692cc33c59804b5a18d7b8a4b79ef0b00b773a27397d1f6"}, - {file = "rpds_py-0.10.6-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:26857f0f44f0e791f4a266595a7a09d21f6b589580ee0585f330aaccccb836e3"}, - {file = "rpds_py-0.10.6-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d7f5e15c953ace2e8dde9824bdab4bec50adb91a5663df08d7d994240ae6fa31"}, - {file = "rpds_py-0.10.6-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:61fa268da6e2e1cd350739bb61011121fa550aa2545762e3dc02ea177ee4de35"}, - {file = "rpds_py-0.10.6-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c48f3fbc3e92c7dd6681a258d22f23adc2eb183c8cb1557d2fcc5a024e80b094"}, - {file = "rpds_py-0.10.6-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c0503c5b681566e8b722fe8c4c47cce5c7a51f6935d5c7012c4aefe952a35eed"}, - {file = "rpds_py-0.10.6-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:734c41f9f57cc28658d98270d3436dba65bed0cfc730d115b290e970150c540d"}, - {file = "rpds_py-0.10.6-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a5d7ed104d158c0042a6a73799cf0eb576dfd5fc1ace9c47996e52320c37cb7c"}, - {file = "rpds_py-0.10.6-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:e3df0bc35e746cce42579826b89579d13fd27c3d5319a6afca9893a9b784ff1b"}, - {file = "rpds_py-0.10.6-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:73e0a78a9b843b8c2128028864901f55190401ba38aae685350cf69b98d9f7c9"}, - {file = "rpds_py-0.10.6-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:5ed505ec6305abd2c2c9586a7b04fbd4baf42d4d684a9c12ec6110deefe2a063"}, - {file = "rpds_py-0.10.6-cp310-none-win32.whl", hash = "sha256:d97dd44683802000277bbf142fd9f6b271746b4846d0acaf0cefa6b2eaf2a7ad"}, - {file = "rpds_py-0.10.6-cp310-none-win_amd64.whl", hash = "sha256:b455492cab07107bfe8711e20cd920cc96003e0da3c1f91297235b1603d2aca7"}, - {file = "rpds_py-0.10.6-cp311-cp311-macosx_10_7_x86_64.whl", hash = "sha256:e8cdd52744f680346ff8c1ecdad5f4d11117e1724d4f4e1874f3a67598821069"}, - {file = "rpds_py-0.10.6-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:66414dafe4326bca200e165c2e789976cab2587ec71beb80f59f4796b786a238"}, - {file = "rpds_py-0.10.6-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cc435d059f926fdc5b05822b1be4ff2a3a040f3ae0a7bbbe672babb468944722"}, - {file = "rpds_py-0.10.6-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8e7f2219cb72474571974d29a191714d822e58be1eb171f229732bc6fdedf0ac"}, - {file = "rpds_py-0.10.6-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3953c6926a63f8ea5514644b7afb42659b505ece4183fdaaa8f61d978754349e"}, - {file = "rpds_py-0.10.6-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2bb2e4826be25e72013916eecd3d30f66fd076110de09f0e750163b416500721"}, - {file = "rpds_py-0.10.6-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7bf347b495b197992efc81a7408e9a83b931b2f056728529956a4d0858608b80"}, - {file = "rpds_py-0.10.6-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:102eac53bb0bf0f9a275b438e6cf6904904908562a1463a6fc3323cf47d7a532"}, - {file = "rpds_py-0.10.6-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:40f93086eef235623aa14dbddef1b9fb4b22b99454cb39a8d2e04c994fb9868c"}, - {file = "rpds_py-0.10.6-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:e22260a4741a0e7a206e175232867b48a16e0401ef5bce3c67ca5b9705879066"}, - {file = "rpds_py-0.10.6-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f4e56860a5af16a0fcfa070a0a20c42fbb2012eed1eb5ceeddcc7f8079214281"}, - {file = "rpds_py-0.10.6-cp311-none-win32.whl", hash = "sha256:0774a46b38e70fdde0c6ded8d6d73115a7c39d7839a164cc833f170bbf539116"}, - {file = "rpds_py-0.10.6-cp311-none-win_amd64.whl", hash = "sha256:4a5ee600477b918ab345209eddafde9f91c0acd931f3776369585a1c55b04c57"}, - {file = "rpds_py-0.10.6-cp312-cp312-macosx_10_7_x86_64.whl", hash = "sha256:5ee97c683eaface61d38ec9a489e353d36444cdebb128a27fe486a291647aff6"}, - {file = "rpds_py-0.10.6-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0713631d6e2d6c316c2f7b9320a34f44abb644fc487b77161d1724d883662e31"}, - {file = "rpds_py-0.10.6-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b5a53f5998b4bbff1cb2e967e66ab2addc67326a274567697379dd1e326bded7"}, - {file = "rpds_py-0.10.6-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6a555ae3d2e61118a9d3e549737bb4a56ff0cec88a22bd1dfcad5b4e04759175"}, - {file = "rpds_py-0.10.6-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:945eb4b6bb8144909b203a88a35e0a03d22b57aefb06c9b26c6e16d72e5eb0f0"}, - {file = "rpds_py-0.10.6-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:52c215eb46307c25f9fd2771cac8135d14b11a92ae48d17968eda5aa9aaf5071"}, - {file = "rpds_py-0.10.6-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c1b3cd23d905589cb205710b3988fc8f46d4a198cf12862887b09d7aaa6bf9b9"}, - {file = "rpds_py-0.10.6-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:64ccc28683666672d7c166ed465c09cee36e306c156e787acef3c0c62f90da5a"}, - {file = "rpds_py-0.10.6-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:516a611a2de12fbea70c78271e558f725c660ce38e0006f75139ba337d56b1f6"}, - {file = "rpds_py-0.10.6-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:9ff93d3aedef11f9c4540cf347f8bb135dd9323a2fc705633d83210d464c579d"}, - {file = "rpds_py-0.10.6-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:d858532212f0650be12b6042ff4378dc2efbb7792a286bee4489eaa7ba010586"}, - {file = "rpds_py-0.10.6-cp312-none-win32.whl", hash = "sha256:3c4eff26eddac49d52697a98ea01b0246e44ca82ab09354e94aae8823e8bda02"}, - {file = "rpds_py-0.10.6-cp312-none-win_amd64.whl", hash = "sha256:150eec465dbc9cbca943c8e557a21afdcf9bab8aaabf386c44b794c2f94143d2"}, - {file = "rpds_py-0.10.6-cp38-cp38-macosx_10_7_x86_64.whl", hash = "sha256:cf693eb4a08eccc1a1b636e4392322582db2a47470d52e824b25eca7a3977b53"}, - {file = "rpds_py-0.10.6-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:4134aa2342f9b2ab6c33d5c172e40f9ef802c61bb9ca30d21782f6e035ed0043"}, - {file = "rpds_py-0.10.6-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e782379c2028a3611285a795b89b99a52722946d19fc06f002f8b53e3ea26ea9"}, - {file = "rpds_py-0.10.6-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2f6da6d842195fddc1cd34c3da8a40f6e99e4a113918faa5e60bf132f917c247"}, - {file = "rpds_py-0.10.6-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b4a9fe992887ac68256c930a2011255bae0bf5ec837475bc6f7edd7c8dfa254e"}, - {file = "rpds_py-0.10.6-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b788276a3c114e9f51e257f2a6f544c32c02dab4aa7a5816b96444e3f9ffc336"}, - {file = "rpds_py-0.10.6-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:caa1afc70a02645809c744eefb7d6ee8fef7e2fad170ffdeacca267fd2674f13"}, - {file = "rpds_py-0.10.6-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:bddd4f91eede9ca5275e70479ed3656e76c8cdaaa1b354e544cbcf94c6fc8ac4"}, - {file = "rpds_py-0.10.6-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:775049dfa63fb58293990fc59473e659fcafd953bba1d00fc5f0631a8fd61977"}, - {file = "rpds_py-0.10.6-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:c6c45a2d2b68c51fe3d9352733fe048291e483376c94f7723458cfd7b473136b"}, - {file = "rpds_py-0.10.6-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:0699ab6b8c98df998c3eacf51a3b25864ca93dab157abe358af46dc95ecd9801"}, - {file = "rpds_py-0.10.6-cp38-none-win32.whl", hash = "sha256:ebdab79f42c5961682654b851f3f0fc68e6cc7cd8727c2ac4ffff955154123c1"}, - {file = "rpds_py-0.10.6-cp38-none-win_amd64.whl", hash = "sha256:24656dc36f866c33856baa3ab309da0b6a60f37d25d14be916bd3e79d9f3afcf"}, - {file = "rpds_py-0.10.6-cp39-cp39-macosx_10_7_x86_64.whl", hash = "sha256:0898173249141ee99ffcd45e3829abe7bcee47d941af7434ccbf97717df020e5"}, - {file = "rpds_py-0.10.6-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:9e9184fa6c52a74a5521e3e87badbf9692549c0fcced47443585876fcc47e469"}, - {file = "rpds_py-0.10.6-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5752b761902cd15073a527b51de76bbae63d938dc7c5c4ad1e7d8df10e765138"}, - {file = "rpds_py-0.10.6-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:99a57006b4ec39dbfb3ed67e5b27192792ffb0553206a107e4aadb39c5004cd5"}, - {file = "rpds_py-0.10.6-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:09586f51a215d17efdb3a5f090d7cbf1633b7f3708f60a044757a5d48a83b393"}, - {file = "rpds_py-0.10.6-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e225a6a14ecf44499aadea165299092ab0cba918bb9ccd9304eab1138844490b"}, - {file = "rpds_py-0.10.6-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b2039f8d545f20c4e52713eea51a275e62153ee96c8035a32b2abb772b6fc9e5"}, - {file = "rpds_py-0.10.6-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:34ad87a831940521d462ac11f1774edf867c34172010f5390b2f06b85dcc6014"}, - {file = "rpds_py-0.10.6-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:dcdc88b6b01015da066da3fb76545e8bb9a6880a5ebf89e0f0b2e3ca557b3ab7"}, - {file = "rpds_py-0.10.6-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:25860ed5c4e7f5e10c496ea78af46ae8d8468e0be745bd233bab9ca99bfd2647"}, - {file = "rpds_py-0.10.6-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:7854a207ef77319ec457c1eb79c361b48807d252d94348305db4f4b62f40f7f3"}, - {file = "rpds_py-0.10.6-cp39-none-win32.whl", hash = "sha256:e6fcc026a3f27c1282c7ed24b7fcac82cdd70a0e84cc848c0841a3ab1e3dea2d"}, - {file = "rpds_py-0.10.6-cp39-none-win_amd64.whl", hash = "sha256:e98c4c07ee4c4b3acf787e91b27688409d918212dfd34c872201273fdd5a0e18"}, - {file = "rpds_py-0.10.6-pp310-pypy310_pp73-macosx_10_7_x86_64.whl", hash = "sha256:68fe9199184c18d997d2e4293b34327c0009a78599ce703e15cd9a0f47349bba"}, - {file = "rpds_py-0.10.6-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:3339eca941568ed52d9ad0f1b8eb9fe0958fa245381747cecf2e9a78a5539c42"}, - {file = "rpds_py-0.10.6-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a360cfd0881d36c6dc271992ce1eda65dba5e9368575663de993eeb4523d895f"}, - {file = "rpds_py-0.10.6-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:031f76fc87644a234883b51145e43985aa2d0c19b063e91d44379cd2786144f8"}, - {file = "rpds_py-0.10.6-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1f36a9d751f86455dc5278517e8b65580eeee37d61606183897f122c9e51cef3"}, - {file = "rpds_py-0.10.6-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:052a832078943d2b2627aea0d19381f607fe331cc0eb5df01991268253af8417"}, - {file = "rpds_py-0.10.6-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:023574366002bf1bd751ebaf3e580aef4a468b3d3c216d2f3f7e16fdabd885ed"}, - {file = "rpds_py-0.10.6-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:defa2c0c68734f4a82028c26bcc85e6b92cced99866af118cd6a89b734ad8e0d"}, - {file = "rpds_py-0.10.6-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:879fb24304ead6b62dbe5034e7b644b71def53c70e19363f3c3be2705c17a3b4"}, - {file = "rpds_py-0.10.6-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:53c43e10d398e365da2d4cc0bcaf0854b79b4c50ee9689652cdc72948e86f487"}, - {file = "rpds_py-0.10.6-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:3777cc9dea0e6c464e4b24760664bd8831738cc582c1d8aacf1c3f546bef3f65"}, - {file = "rpds_py-0.10.6-pp38-pypy38_pp73-macosx_10_7_x86_64.whl", hash = "sha256:40578a6469e5d1df71b006936ce95804edb5df47b520c69cf5af264d462f2cbb"}, - {file = "rpds_py-0.10.6-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:cf71343646756a072b85f228d35b1d7407da1669a3de3cf47f8bbafe0c8183a4"}, - {file = "rpds_py-0.10.6-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:10f32b53f424fc75ff7b713b2edb286fdbfc94bf16317890260a81c2c00385dc"}, - {file = "rpds_py-0.10.6-pp38-pypy38_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:81de24a1c51cfb32e1fbf018ab0bdbc79c04c035986526f76c33e3f9e0f3356c"}, - {file = "rpds_py-0.10.6-pp38-pypy38_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ac17044876e64a8ea20ab132080ddc73b895b4abe9976e263b0e30ee5be7b9c2"}, - {file = "rpds_py-0.10.6-pp38-pypy38_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5e8a78bd4879bff82daef48c14d5d4057f6856149094848c3ed0ecaf49f5aec2"}, - {file = "rpds_py-0.10.6-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:78ca33811e1d95cac8c2e49cb86c0fb71f4d8409d8cbea0cb495b6dbddb30a55"}, - {file = "rpds_py-0.10.6-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c63c3ef43f0b3fb00571cff6c3967cc261c0ebd14a0a134a12e83bdb8f49f21f"}, - {file = "rpds_py-0.10.6-pp38-pypy38_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:7fde6d0e00b2fd0dbbb40c0eeec463ef147819f23725eda58105ba9ca48744f4"}, - {file = "rpds_py-0.10.6-pp38-pypy38_pp73-musllinux_1_2_i686.whl", hash = "sha256:79edd779cfc46b2e15b0830eecd8b4b93f1a96649bcb502453df471a54ce7977"}, - {file = "rpds_py-0.10.6-pp38-pypy38_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:9164ec8010327ab9af931d7ccd12ab8d8b5dc2f4c6a16cbdd9d087861eaaefa1"}, - {file = "rpds_py-0.10.6-pp39-pypy39_pp73-macosx_10_7_x86_64.whl", hash = "sha256:d29ddefeab1791e3c751e0189d5f4b3dbc0bbe033b06e9c333dca1f99e1d523e"}, - {file = "rpds_py-0.10.6-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:30adb75ecd7c2a52f5e76af50644b3e0b5ba036321c390b8e7ec1bb2a16dd43c"}, - {file = "rpds_py-0.10.6-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dd609fafdcdde6e67a139898196698af37438b035b25ad63704fd9097d9a3482"}, - {file = "rpds_py-0.10.6-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6eef672de005736a6efd565577101277db6057f65640a813de6c2707dc69f396"}, - {file = "rpds_py-0.10.6-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6cf4393c7b41abbf07c88eb83e8af5013606b1cdb7f6bc96b1b3536b53a574b8"}, - {file = "rpds_py-0.10.6-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ad857f42831e5b8d41a32437f88d86ead6c191455a3499c4b6d15e007936d4cf"}, - {file = "rpds_py-0.10.6-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1d7360573f1e046cb3b0dceeb8864025aa78d98be4bb69f067ec1c40a9e2d9df"}, - {file = "rpds_py-0.10.6-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d08f63561c8a695afec4975fae445245386d645e3e446e6f260e81663bfd2e38"}, - {file = "rpds_py-0.10.6-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:f0f17f2ce0f3529177a5fff5525204fad7b43dd437d017dd0317f2746773443d"}, - {file = "rpds_py-0.10.6-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:442626328600bde1d09dc3bb00434f5374948838ce75c41a52152615689f9403"}, - {file = "rpds_py-0.10.6-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:e9616f5bd2595f7f4a04b67039d890348ab826e943a9bfdbe4938d0eba606971"}, - {file = "rpds_py-0.10.6.tar.gz", hash = "sha256:4ce5a708d65a8dbf3748d2474b580d606b1b9f91b5c6ab2a316e0b0cf7a4ba50"}, + {file = "rpds_py-0.12.0-cp310-cp310-macosx_10_7_x86_64.whl", hash = "sha256:c694bee70ece3b232df4678448fdda245fd3b1bb4ba481fb6cd20e13bb784c46"}, + {file = "rpds_py-0.12.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:30e5ce9f501fb1f970e4a59098028cf20676dee64fc496d55c33e04bbbee097d"}, + {file = "rpds_py-0.12.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d72a4315514e5a0b9837a086cb433b004eea630afb0cc129de76d77654a9606f"}, + {file = "rpds_py-0.12.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:eebaf8c76c39604d52852366249ab807fe6f7a3ffb0dd5484b9944917244cdbe"}, + {file = "rpds_py-0.12.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a239303acb0315091d54c7ff36712dba24554993b9a93941cf301391d8a997ee"}, + {file = "rpds_py-0.12.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ced40cdbb6dd47a032725a038896cceae9ce267d340f59508b23537f05455431"}, + {file = "rpds_py-0.12.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3c8c0226c71bd0ce9892eaf6afa77ae8f43a3d9313124a03df0b389c01f832de"}, + {file = "rpds_py-0.12.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b8e11715178f3608874508f08e990d3771e0b8c66c73eb4e183038d600a9b274"}, + {file = "rpds_py-0.12.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:5210a0018c7e09c75fa788648617ebba861ae242944111d3079034e14498223f"}, + {file = "rpds_py-0.12.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:171d9a159f1b2f42a42a64a985e4ba46fc7268c78299272ceba970743a67ee50"}, + {file = "rpds_py-0.12.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:57ec6baec231bb19bb5fd5fc7bae21231860a1605174b11585660236627e390e"}, + {file = "rpds_py-0.12.0-cp310-none-win32.whl", hash = "sha256:7188ddc1a8887194f984fa4110d5a3d5b9b5cd35f6bafdff1b649049cbc0ce29"}, + {file = "rpds_py-0.12.0-cp310-none-win_amd64.whl", hash = "sha256:1e04581c6117ad9479b6cfae313e212fe0dfa226ac727755f0d539cd54792963"}, + {file = "rpds_py-0.12.0-cp311-cp311-macosx_10_7_x86_64.whl", hash = "sha256:0a38612d07a36138507d69646c470aedbfe2b75b43a4643f7bd8e51e52779624"}, + {file = "rpds_py-0.12.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f12d69d568f5647ec503b64932874dade5a20255736c89936bf690951a5e79f5"}, + {file = "rpds_py-0.12.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4f8a1d990dc198a6c68ec3d9a637ba1ce489b38cbfb65440a27901afbc5df575"}, + {file = "rpds_py-0.12.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8c567c664fc2f44130a20edac73e0a867f8e012bf7370276f15c6adc3586c37c"}, + {file = "rpds_py-0.12.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0e9e976e0dbed4f51c56db10831c9623d0fd67aac02853fe5476262e5a22acb7"}, + {file = "rpds_py-0.12.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:efddca2d02254a52078c35cadad34762adbae3ff01c6b0c7787b59d038b63e0d"}, + {file = "rpds_py-0.12.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d9e7f29c00577aff6b318681e730a519b235af292732a149337f6aaa4d1c5e31"}, + {file = "rpds_py-0.12.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:389c0e38358fdc4e38e9995e7291269a3aead7acfcf8942010ee7bc5baee091c"}, + {file = "rpds_py-0.12.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:33ab498f9ac30598b6406e2be1b45fd231195b83d948ebd4bd77f337cb6a2bff"}, + {file = "rpds_py-0.12.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:d56b1cd606ba4cedd64bb43479d56580e147c6ef3f5d1c5e64203a1adab784a2"}, + {file = "rpds_py-0.12.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1fa73ed22c40a1bec98d7c93b5659cd35abcfa5a0a95ce876b91adbda170537c"}, + {file = "rpds_py-0.12.0-cp311-none-win32.whl", hash = "sha256:dbc25baa6abb205766fb8606f8263b02c3503a55957fcb4576a6bb0a59d37d10"}, + {file = "rpds_py-0.12.0-cp311-none-win_amd64.whl", hash = "sha256:c6b52b7028b547866c2413f614ee306c2d4eafdd444b1ff656bf3295bf1484aa"}, + {file = "rpds_py-0.12.0-cp312-cp312-macosx_10_7_x86_64.whl", hash = "sha256:9620650c364c01ed5b497dcae7c3d4b948daeae6e1883ae185fef1c927b6b534"}, + {file = "rpds_py-0.12.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2124f9e645a94ab7c853bc0a3644e0ca8ffbe5bb2d72db49aef8f9ec1c285733"}, + {file = "rpds_py-0.12.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:281c8b219d4f4b3581b918b816764098d04964915b2f272d1476654143801aa2"}, + {file = "rpds_py-0.12.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:27ccc93c7457ef890b0dd31564d2a05e1aca330623c942b7e818e9e7c2669ee4"}, + {file = "rpds_py-0.12.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d1c562a9bb72244fa767d1c1ab55ca1d92dd5f7c4d77878fee5483a22ffac808"}, + {file = "rpds_py-0.12.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e57919c32ee295a2fca458bb73e4b20b05c115627f96f95a10f9f5acbd61172d"}, + {file = "rpds_py-0.12.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fa35ad36440aaf1ac8332b4a4a433d4acd28f1613f0d480995f5cfd3580e90b7"}, + {file = "rpds_py-0.12.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e6aea5c0eb5b0faf52c7b5c4a47c8bb64437173be97227c819ffa31801fa4e34"}, + {file = "rpds_py-0.12.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:81cf9d306c04df1b45971c13167dc3bad625808aa01281d55f3cf852dde0e206"}, + {file = "rpds_py-0.12.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:08e6e7ff286254016b945e1ab632ee843e43d45e40683b66dd12b73791366dd1"}, + {file = "rpds_py-0.12.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:4d0a675a7acbbc16179188d8c6d0afb8628604fc1241faf41007255957335a0b"}, + {file = "rpds_py-0.12.0-cp312-none-win32.whl", hash = "sha256:b2287c09482949e0ca0c0eb68b2aca6cf57f8af8c6dfd29dcd3bc45f17b57978"}, + {file = "rpds_py-0.12.0-cp312-none-win_amd64.whl", hash = "sha256:8015835494b21aa7abd3b43fdea0614ee35ef6b03db7ecba9beb58eadf01c24f"}, + {file = "rpds_py-0.12.0-cp38-cp38-macosx_10_7_x86_64.whl", hash = "sha256:6174d6ad6b58a6bcf67afbbf1723420a53d06c4b89f4c50763d6fa0a6ac9afd2"}, + {file = "rpds_py-0.12.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:a689e1ded7137552bea36305a7a16ad2b40be511740b80748d3140614993db98"}, + {file = "rpds_py-0.12.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f45321224144c25a62052035ce96cbcf264667bcb0d81823b1bbc22c4addd194"}, + {file = "rpds_py-0.12.0-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:aa32205358a76bf578854bf31698a86dc8b2cb591fd1d79a833283f4a403f04b"}, + {file = "rpds_py-0.12.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:91bd2b7cf0f4d252eec8b7046fa6a43cee17e8acdfc00eaa8b3dbf2f9a59d061"}, + {file = "rpds_py-0.12.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3acadbab8b59f63b87b518e09c4c64b142e7286b9ca7a208107d6f9f4c393c5c"}, + {file = "rpds_py-0.12.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:429349a510da82c85431f0f3e66212d83efe9fd2850f50f339341b6532c62fe4"}, + {file = "rpds_py-0.12.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:05942656cb2cb4989cd50ced52df16be94d344eae5097e8583966a1d27da73a5"}, + {file = "rpds_py-0.12.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:0c5441b7626c29dbd54a3f6f3713ec8e956b009f419ffdaaa3c80eaf98ddb523"}, + {file = "rpds_py-0.12.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:b6b0e17d39d21698185097652c611f9cf30f7c56ccec189789920e3e7f1cee56"}, + {file = "rpds_py-0.12.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:3b7a64d43e2a1fa2dd46b678e00cabd9a49ebb123b339ce799204c44a593ae1c"}, + {file = "rpds_py-0.12.0-cp38-none-win32.whl", hash = "sha256:e5bbe011a2cea9060fef1bb3d668a2fd8432b8888e6d92e74c9c794d3c101595"}, + {file = "rpds_py-0.12.0-cp38-none-win_amd64.whl", hash = "sha256:bec29b801b4adbf388314c0d050e851d53762ab424af22657021ce4b6eb41543"}, + {file = "rpds_py-0.12.0-cp39-cp39-macosx_10_7_x86_64.whl", hash = "sha256:1096ca0bf2d3426cbe79d4ccc91dc5aaa73629b08ea2d8467375fad8447ce11a"}, + {file = "rpds_py-0.12.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:48aa98987d54a46e13e6954880056c204700c65616af4395d1f0639eba11764b"}, + {file = "rpds_py-0.12.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7979d90ee2190d000129598c2b0c82f13053dba432b94e45e68253b09bb1f0f6"}, + {file = "rpds_py-0.12.0-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:88857060b690a57d2ea8569bca58758143c8faa4639fb17d745ce60ff84c867e"}, + {file = "rpds_py-0.12.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4eb74d44776b0fb0782560ea84d986dffec8ddd94947f383eba2284b0f32e35e"}, + {file = "rpds_py-0.12.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f62581d7e884dd01ee1707b7c21148f61f2febb7de092ae2f108743fcbef5985"}, + {file = "rpds_py-0.12.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6f5dcb658d597410bb7c967c1d24eaf9377b0d621358cbe9d2ff804e5dd12e81"}, + {file = "rpds_py-0.12.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9bf9acce44e967a5103fcd820fc7580c7b0ab8583eec4e2051aec560f7b31a63"}, + {file = "rpds_py-0.12.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:240687b5be0f91fbde4936a329c9b7589d9259742766f74de575e1b2046575e4"}, + {file = "rpds_py-0.12.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:25740fb56e8bd37692ed380e15ec734be44d7c71974d8993f452b4527814601e"}, + {file = "rpds_py-0.12.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:a54917b7e9cd3a67e429a630e237a90b096e0ba18897bfb99ee8bd1068a5fea0"}, + {file = "rpds_py-0.12.0-cp39-none-win32.whl", hash = "sha256:b92aafcfab3d41580d54aca35a8057341f1cfc7c9af9e8bdfc652f83a20ced31"}, + {file = "rpds_py-0.12.0-cp39-none-win_amd64.whl", hash = "sha256:cd316dbcc74c76266ba94eb021b0cc090b97cca122f50bd7a845f587ff4bf03f"}, + {file = "rpds_py-0.12.0-pp310-pypy310_pp73-macosx_10_7_x86_64.whl", hash = "sha256:0853da3d5e9bc6a07b2486054a410b7b03f34046c123c6561b535bb48cc509e1"}, + {file = "rpds_py-0.12.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:cb41ad20064e18a900dd427d7cf41cfaec83bcd1184001f3d91a1f76b3fcea4e"}, + {file = "rpds_py-0.12.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b710bf7e7ae61957d5c4026b486be593ed3ec3dca3e5be15e0f6d8cf5d0a4990"}, + {file = "rpds_py-0.12.0-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a952ae3eb460c6712388ac2ec706d24b0e651b9396d90c9a9e0a69eb27737fdc"}, + {file = "rpds_py-0.12.0-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0bedd91ae1dd142a4dc15970ed2c729ff6c73f33a40fa84ed0cdbf55de87c777"}, + {file = "rpds_py-0.12.0-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:761531076df51309075133a6bc1db02d98ec7f66e22b064b1d513bc909f29743"}, + {file = "rpds_py-0.12.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a2baa6be130e8a00b6cbb9f18a33611ec150b4537f8563bddadb54c1b74b8193"}, + {file = "rpds_py-0.12.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f05450fa1cd7c525c0b9d1a7916e595d3041ac0afbed2ff6926e5afb6a781b7f"}, + {file = "rpds_py-0.12.0-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:81c4d1a3a564775c44732b94135d06e33417e829ff25226c164664f4a1046213"}, + {file = "rpds_py-0.12.0-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:e888be685fa42d8b8a3d3911d5604d14db87538aa7d0b29b1a7ea80d354c732d"}, + {file = "rpds_py-0.12.0-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:6f8d7fe73d1816eeb5378409adc658f9525ecbfaf9e1ede1e2d67a338b0c7348"}, + {file = "rpds_py-0.12.0-pp38-pypy38_pp73-macosx_10_7_x86_64.whl", hash = "sha256:0831d3ecdea22e4559cc1793f22e77067c9d8c451d55ae6a75bf1d116a8e7f42"}, + {file = "rpds_py-0.12.0-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:513ccbf7420c30e283c25c82d5a8f439d625a838d3ba69e79a110c260c46813f"}, + {file = "rpds_py-0.12.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:301bd744a1adaa2f6a5e06c98f1ac2b6f8dc31a5c23b838f862d65e32fca0d4b"}, + {file = "rpds_py-0.12.0-pp38-pypy38_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f8832a4f83d4782a8f5a7b831c47e8ffe164e43c2c148c8160ed9a6d630bc02a"}, + {file = "rpds_py-0.12.0-pp38-pypy38_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4b2416ed743ec5debcf61e1242e012652a4348de14ecc7df3512da072b074440"}, + {file = "rpds_py-0.12.0-pp38-pypy38_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:35585a8cb5917161f42c2104567bb83a1d96194095fc54a543113ed5df9fa436"}, + {file = "rpds_py-0.12.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d389ff1e95b6e46ebedccf7fd1fadd10559add595ac6a7c2ea730268325f832c"}, + {file = "rpds_py-0.12.0-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9b007c2444705a2dc4a525964fd4dd28c3320b19b3410da6517cab28716f27d3"}, + {file = "rpds_py-0.12.0-pp38-pypy38_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:188912b22b6c8225f4c4ffa020a2baa6ad8fabb3c141a12dbe6edbb34e7f1425"}, + {file = "rpds_py-0.12.0-pp38-pypy38_pp73-musllinux_1_2_i686.whl", hash = "sha256:1b4cf9ab9a0ae0cb122685209806d3f1dcb63b9fccdf1424fb42a129dc8c2faa"}, + {file = "rpds_py-0.12.0-pp38-pypy38_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:2d34a5450a402b00d20aeb7632489ffa2556ca7b26f4a63c35f6fccae1977427"}, + {file = "rpds_py-0.12.0-pp39-pypy39_pp73-macosx_10_7_x86_64.whl", hash = "sha256:466030a42724780794dea71eb32db83cc51214d66ab3fb3156edd88b9c8f0d78"}, + {file = "rpds_py-0.12.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:68172622a5a57deb079a2c78511c40f91193548e8ab342c31e8cb0764d362459"}, + {file = "rpds_py-0.12.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:54cdfcda59251b9c2f87a05d038c2ae02121219a04d4a1e6fc345794295bdc07"}, + {file = "rpds_py-0.12.0-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6b75b912a0baa033350367a8a07a8b2d44fd5b90c890bfbd063a8a5f945f644b"}, + {file = "rpds_py-0.12.0-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:47aeceb4363851d17f63069318ba5721ae695d9da55d599b4d6fb31508595278"}, + {file = "rpds_py-0.12.0-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0525847f83f506aa1e28eb2057b696fe38217e12931c8b1b02198cfe6975e142"}, + {file = "rpds_py-0.12.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:efbe0b5e0fd078ed7b005faa0170da4f72666360f66f0bb2d7f73526ecfd99f9"}, + {file = "rpds_py-0.12.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:0fadfdda275c838cba5102c7f90a20f2abd7727bf8f4a2b654a5b617529c5c18"}, + {file = "rpds_py-0.12.0-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:56dd500411d03c5e9927a1eb55621e906837a83b02350a9dc401247d0353717c"}, + {file = "rpds_py-0.12.0-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:6915fc9fa6b3ec3569566832e1bb03bd801c12cea030200e68663b9a87974e76"}, + {file = "rpds_py-0.12.0-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:5f1519b080d8ce0a814f17ad9fb49fb3a1d4d7ce5891f5c85fc38631ca3a8dc4"}, + {file = "rpds_py-0.12.0.tar.gz", hash = "sha256:7036316cc26b93e401cedd781a579be606dad174829e6ad9e9c5a0da6e036f80"}, ] [[package]] @@ -2700,6 +2699,22 @@ nativelib = ["pyobjc-framework-Cocoa", "pywin32"] objc = ["pyobjc-framework-Cocoa"] win32 = ["pywin32"] +[[package]] +name = "setuptools" +version = "68.2.2" +description = "Easily download, build, install, upgrade, and uninstall Python packages" +optional = false +python-versions = ">=3.8" +files = [ + {file = "setuptools-68.2.2-py3-none-any.whl", hash = "sha256:b454a35605876da60632df1a60f736524eb73cc47bbc9f3f1ef1b644de74fd2a"}, + {file = "setuptools-68.2.2.tar.gz", hash = "sha256:4ac1475276d2f1c48684874089fefcd83bd7162ddaafb81fac866ba0db282a87"}, +] + +[package.extras] +docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-hoverxref (<2)", "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" @@ -2816,22 +2831,22 @@ test = ["cython (>=3.0)", "filelock", "html5lib", "pytest (>=4.6)", "setuptools [[package]] name = "sphinx-autodoc-typehints" -version = "1.24.0" +version = "1.25.2" description = "Type hints (PEP 484) support for the Sphinx autodoc extension" optional = true python-versions = ">=3.8" files = [ - {file = "sphinx_autodoc_typehints-1.24.0-py3-none-any.whl", hash = "sha256:6a73c0c61a9144ce2ed5ef2bed99d615254e5005c1cc32002017d72d69fb70e6"}, - {file = "sphinx_autodoc_typehints-1.24.0.tar.gz", hash = "sha256:94e440066941bb237704bb880785e2d05e8ae5406c88674feefbb938ad0dc6af"}, + {file = "sphinx_autodoc_typehints-1.25.2-py3-none-any.whl", hash = "sha256:5ed05017d23ad4b937eab3bee9fae9ab0dd63f0b42aa360031f1fad47e47f673"}, + {file = "sphinx_autodoc_typehints-1.25.2.tar.gz", hash = "sha256:3cabc2537e17989b2f92e64a399425c4c8bf561ed73f087bc7414a5003616a50"}, ] [package.dependencies] -sphinx = ">=7.0.1" +sphinx = ">=7.1.2" [package.extras] -docs = ["furo (>=2023.5.20)", "sphinx (>=7.0.1)"] +docs = ["furo (>=2023.7.26)", "sphinx (>=7.1.2)"] numpy = ["nptyping (>=2.5)"] -testing = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "diff-cover (>=7.5)", "pytest (>=7.3.1)", "pytest-cov (>=4.1)", "sphobjinv (>=2.3.1)", "typing-extensions (>=4.6.3)"] +testing = ["covdefaults (>=2.3)", "coverage (>=7.3)", "diff-cover (>=7.7)", "pytest (>=7.4)", "pytest-cov (>=4.1)", "sphobjinv (>=2.3.1)", "typing-extensions (>=4.7.1)"] [[package]] name = "sphinxcontrib-applehelp" @@ -3033,13 +3048,13 @@ tests = ["cython", "littleutils", "pygments", "pytest", "typeguard"] [[package]] name = "terminado" -version = "0.17.1" +version = "0.18.0" description = "Tornado websocket backend for the Xterm.js Javascript terminal emulator library." optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "terminado-0.17.1-py3-none-any.whl", hash = "sha256:8650d44334eba354dd591129ca3124a6ba42c3d5b70df5051b6921d506fdaeae"}, - {file = "terminado-0.17.1.tar.gz", hash = "sha256:6ccbbcd3a4f8a25a5ec04991f39a0b8db52dfcd487ea0e578d977e6752380333"}, + {file = "terminado-0.18.0-py3-none-any.whl", hash = "sha256:87b0d96642d0fe5f5abd7783857b9cab167f221a39ff98e3b9619a788a3c0f2e"}, + {file = "terminado-0.18.0.tar.gz", hash = "sha256:1ea08a89b835dd1b8c0c900d92848147cef2537243361b2e3f4dc15df9b6fded"}, ] [package.dependencies] @@ -3050,6 +3065,7 @@ tornado = ">=6.1.0" [package.extras] docs = ["myst-parser", "pydata-sphinx-theme", "sphinx"] test = ["pre-commit", "pytest (>=7.0)", "pytest-timeout"] +typing = ["mypy (>=1.6,<2.0)", "traitlets (>=5.11.1)"] [[package]] name = "tinycss2" @@ -3102,18 +3118,18 @@ files = [ [[package]] name = "traitlets" -version = "5.11.2" +version = "5.13.0" description = "Traitlets Python configuration system" optional = false python-versions = ">=3.8" files = [ - {file = "traitlets-5.11.2-py3-none-any.whl", hash = "sha256:98277f247f18b2c5cabaf4af369187754f4fb0e85911d473f72329db8a7f4fae"}, - {file = "traitlets-5.11.2.tar.gz", hash = "sha256:7564b5bf8d38c40fa45498072bf4dc5e8346eb087bbf1e2ae2d8774f6a0f078e"}, + {file = "traitlets-5.13.0-py3-none-any.whl", hash = "sha256:baf991e61542da48fe8aef8b779a9ea0aa38d8a54166ee250d5af5ecf4486619"}, + {file = "traitlets-5.13.0.tar.gz", hash = "sha256:9b232b9430c8f57288c1024b34a8f0251ddcc47268927367a0dd3eeaca40deb5"}, ] [package.extras] docs = ["myst-parser", "pydata-sphinx-theme", "sphinx"] -test = ["argcomplete (>=3.0.3)", "mypy (>=1.5.1)", "pre-commit", "pytest (>=7.0,<7.5)", "pytest-mock", "pytest-mypy-testing"] +test = ["argcomplete (>=3.0.3)", "mypy (>=1.6.0)", "pre-commit", "pytest (>=7.0,<7.5)", "pytest-mock", "pytest-mypy-testing"] [[package]] name = "types-click" @@ -3169,13 +3185,13 @@ files = [ [[package]] name = "types-pyopenssl" -version = "23.2.0.2" +version = "23.3.0.0" description = "Typing stubs for pyOpenSSL" optional = false -python-versions = "*" +python-versions = ">=3.7" files = [ - {file = "types-pyOpenSSL-23.2.0.2.tar.gz", hash = "sha256:6a010dac9ecd42b582d7dd2cc3e9e40486b79b3b64bb2fffba1474ff96af906d"}, - {file = "types_pyOpenSSL-23.2.0.2-py3-none-any.whl", hash = "sha256:19536aa3debfbe25a918cf0d898e9f5fbbe6f3594a429da7914bf331deb1b342"}, + {file = "types-pyOpenSSL-23.3.0.0.tar.gz", hash = "sha256:5ffb077fe70b699c88d5caab999ae80e192fe28bf6cda7989b7e79b1e4e2dcd3"}, + {file = "types_pyOpenSSL-23.3.0.0-py3-none-any.whl", hash = "sha256:00171433653265843b7469ddb9f3c86d698668064cc33ef10537822156130ebf"}, ] [package.dependencies] @@ -3194,13 +3210,13 @@ files = [ [[package]] name = "types-redis" -version = "4.6.0.7" +version = "4.6.0.10" description = "Typing stubs for redis" optional = false -python-versions = "*" +python-versions = ">=3.7" files = [ - {file = "types-redis-4.6.0.7.tar.gz", hash = "sha256:28c4153ddb5c9d4f10def44a2454673c361d2d5fc3cd867cf3bb1520f3f59a38"}, - {file = "types_redis-4.6.0.7-py3-none-any.whl", hash = "sha256:05b1bf92879b25df20433fa1af07784a0d7928c616dc2ebf9087618db77ccbd0"}, + {file = "types-redis-4.6.0.10.tar.gz", hash = "sha256:aa7fb5f743534500f274ddf11ab1c910aae1020481865a36b799e1d67de2aaf3"}, + {file = "types_redis-4.6.0.10-py3-none-any.whl", hash = "sha256:00f003da884ec3d1d54633186b4cbd587b39782595c5603330cc46a51f9bcf6e"}, ] [package.dependencies] @@ -3288,13 +3304,13 @@ dev = ["flake8", "flake8-annotations", "flake8-bandit", "flake8-bugbear", "flake [[package]] name = "urllib3" -version = "2.0.7" +version = "2.1.0" description = "HTTP library with thread-safe connection pooling, file post, and more." optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "urllib3-2.0.7-py3-none-any.whl", hash = "sha256:fdb6d215c776278489906c2f8916e6e7d4f5a9b602ccbcfdf7f016fc8da0596e"}, - {file = "urllib3-2.0.7.tar.gz", hash = "sha256:c97dfde1f7bd43a71c8d2a58e369e9b2bf692d1334ea9f9cae55add7d0dd0f84"}, + {file = "urllib3-2.1.0-py3-none-any.whl", hash = "sha256:55901e917a5896a349ff771be919f8bd99aff50b79fe58fec595eb37bbc56bb3"}, + {file = "urllib3-2.1.0.tar.gz", hash = "sha256:df7aa8afb0148fa78488e7899b2c59b5f4ffcfa82e6c54ccb9dd37c1d7b52d54"}, ] [package.dependencies] @@ -3303,7 +3319,6 @@ brotlicffi = {version = ">=0.8.0", optional = true, markers = "platform_python_i [package.extras] brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"] -secure = ["certifi", "cryptography (>=1.9)", "idna (>=2.0.0)", "pyopenssl (>=17.1.0)", "urllib3-secure-extra"] socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] zstd = ["zstandard (>=0.18.0)"] @@ -3331,13 +3346,13 @@ tooling-extras = ["pyaml (>=23.7.0)", "pypandoc-binary (>=1.11)", "pytest (>=7.4 [[package]] name = "wcwidth" -version = "0.2.8" +version = "0.2.10" description = "Measures the displayed width of unicode strings in a terminal" optional = false python-versions = "*" files = [ - {file = "wcwidth-0.2.8-py2.py3-none-any.whl", hash = "sha256:77f719e01648ed600dfa5402c347481c0992263b81a027344f3e1ba25493a704"}, - {file = "wcwidth-0.2.8.tar.gz", hash = "sha256:8705c569999ffbb4f6a87c6d1b80f324bd6db952f5eb0b95bc07517f4c1813d4"}, + {file = "wcwidth-0.2.10-py2.py3-none-any.whl", hash = "sha256:aec5179002dd0f0d40c456026e74a729661c9d468e1ed64405e3a6c2176ca36f"}, + {file = "wcwidth-0.2.10.tar.gz", hash = "sha256:390c7454101092a6a5e43baad8f83de615463af459201709556b6e4b1c861f97"}, ] [[package]] @@ -3394,86 +3409,81 @@ files = [ [[package]] name = "wrapt" -version = "1.15.0" +version = "1.16.0" description = "Module for decorators, wrappers and monkey patching." optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" +python-versions = ">=3.6" files = [ - {file = "wrapt-1.15.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:ca1cccf838cd28d5a0883b342474c630ac48cac5df0ee6eacc9c7290f76b11c1"}, - {file = "wrapt-1.15.0-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:e826aadda3cae59295b95343db8f3d965fb31059da7de01ee8d1c40a60398b29"}, - {file = "wrapt-1.15.0-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:5fc8e02f5984a55d2c653f5fea93531e9836abbd84342c1d1e17abc4a15084c2"}, - {file = "wrapt-1.15.0-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:96e25c8603a155559231c19c0349245eeb4ac0096fe3c1d0be5c47e075bd4f46"}, - {file = "wrapt-1.15.0-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:40737a081d7497efea35ab9304b829b857f21558acfc7b3272f908d33b0d9d4c"}, - {file = "wrapt-1.15.0-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:f87ec75864c37c4c6cb908d282e1969e79763e0d9becdfe9fe5473b7bb1e5f09"}, - {file = "wrapt-1.15.0-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:1286eb30261894e4c70d124d44b7fd07825340869945c79d05bda53a40caa079"}, - {file = "wrapt-1.15.0-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:493d389a2b63c88ad56cdc35d0fa5752daac56ca755805b1b0c530f785767d5e"}, - {file = "wrapt-1.15.0-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:58d7a75d731e8c63614222bcb21dd992b4ab01a399f1f09dd82af17bbfc2368a"}, - {file = "wrapt-1.15.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:21f6d9a0d5b3a207cdf7acf8e58d7d13d463e639f0c7e01d82cdb671e6cb7923"}, - {file = "wrapt-1.15.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ce42618f67741d4697684e501ef02f29e758a123aa2d669e2d964ff734ee00ee"}, - {file = "wrapt-1.15.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:41d07d029dd4157ae27beab04d22b8e261eddfc6ecd64ff7000b10dc8b3a5727"}, - {file = "wrapt-1.15.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:54accd4b8bc202966bafafd16e69da9d5640ff92389d33d28555c5fd4f25ccb7"}, - {file = "wrapt-1.15.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2fbfbca668dd15b744418265a9607baa970c347eefd0db6a518aaf0cfbd153c0"}, - {file = "wrapt-1.15.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:76e9c727a874b4856d11a32fb0b389afc61ce8aaf281ada613713ddeadd1cfec"}, - {file = "wrapt-1.15.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e20076a211cd6f9b44a6be58f7eeafa7ab5720eb796975d0c03f05b47d89eb90"}, - {file = "wrapt-1.15.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a74d56552ddbde46c246b5b89199cb3fd182f9c346c784e1a93e4dc3f5ec9975"}, - {file = "wrapt-1.15.0-cp310-cp310-win32.whl", hash = "sha256:26458da5653aa5b3d8dc8b24192f574a58984c749401f98fff994d41d3f08da1"}, - {file = "wrapt-1.15.0-cp310-cp310-win_amd64.whl", hash = "sha256:75760a47c06b5974aa5e01949bf7e66d2af4d08cb8c1d6516af5e39595397f5e"}, - {file = "wrapt-1.15.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ba1711cda2d30634a7e452fc79eabcadaffedf241ff206db2ee93dd2c89a60e7"}, - {file = "wrapt-1.15.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:56374914b132c702aa9aa9959c550004b8847148f95e1b824772d453ac204a72"}, - {file = "wrapt-1.15.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a89ce3fd220ff144bd9d54da333ec0de0399b52c9ac3d2ce34b569cf1a5748fb"}, - {file = "wrapt-1.15.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3bbe623731d03b186b3d6b0d6f51865bf598587c38d6f7b0be2e27414f7f214e"}, - {file = "wrapt-1.15.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3abbe948c3cbde2689370a262a8d04e32ec2dd4f27103669a45c6929bcdbfe7c"}, - {file = "wrapt-1.15.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:b67b819628e3b748fd3c2192c15fb951f549d0f47c0449af0764d7647302fda3"}, - {file = "wrapt-1.15.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:7eebcdbe3677e58dd4c0e03b4f2cfa346ed4049687d839adad68cc38bb559c92"}, - {file = "wrapt-1.15.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:74934ebd71950e3db69960a7da29204f89624dde411afbfb3b4858c1409b1e98"}, - {file = "wrapt-1.15.0-cp311-cp311-win32.whl", hash = "sha256:bd84395aab8e4d36263cd1b9308cd504f6cf713b7d6d3ce25ea55670baec5416"}, - {file = "wrapt-1.15.0-cp311-cp311-win_amd64.whl", hash = "sha256:a487f72a25904e2b4bbc0817ce7a8de94363bd7e79890510174da9d901c38705"}, - {file = "wrapt-1.15.0-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:4ff0d20f2e670800d3ed2b220d40984162089a6e2c9646fdb09b85e6f9a8fc29"}, - {file = "wrapt-1.15.0-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:9ed6aa0726b9b60911f4aed8ec5b8dd7bf3491476015819f56473ffaef8959bd"}, - {file = "wrapt-1.15.0-cp35-cp35m-manylinux2010_i686.whl", hash = "sha256:896689fddba4f23ef7c718279e42f8834041a21342d95e56922e1c10c0cc7afb"}, - {file = "wrapt-1.15.0-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:75669d77bb2c071333417617a235324a1618dba66f82a750362eccbe5b61d248"}, - {file = "wrapt-1.15.0-cp35-cp35m-win32.whl", hash = "sha256:fbec11614dba0424ca72f4e8ba3c420dba07b4a7c206c8c8e4e73f2e98f4c559"}, - {file = "wrapt-1.15.0-cp35-cp35m-win_amd64.whl", hash = "sha256:fd69666217b62fa5d7c6aa88e507493a34dec4fa20c5bd925e4bc12fce586639"}, - {file = "wrapt-1.15.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:b0724f05c396b0a4c36a3226c31648385deb6a65d8992644c12a4963c70326ba"}, - {file = "wrapt-1.15.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bbeccb1aa40ab88cd29e6c7d8585582c99548f55f9b2581dfc5ba68c59a85752"}, - {file = "wrapt-1.15.0-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:38adf7198f8f154502883242f9fe7333ab05a5b02de7d83aa2d88ea621f13364"}, - {file = "wrapt-1.15.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:578383d740457fa790fdf85e6d346fda1416a40549fe8db08e5e9bd281c6a475"}, - {file = "wrapt-1.15.0-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:a4cbb9ff5795cd66f0066bdf5947f170f5d63a9274f99bdbca02fd973adcf2a8"}, - {file = "wrapt-1.15.0-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:af5bd9ccb188f6a5fdda9f1f09d9f4c86cc8a539bd48a0bfdc97723970348418"}, - {file = "wrapt-1.15.0-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:b56d5519e470d3f2fe4aa7585f0632b060d532d0696c5bdfb5e8319e1d0f69a2"}, - {file = "wrapt-1.15.0-cp36-cp36m-win32.whl", hash = "sha256:77d4c1b881076c3ba173484dfa53d3582c1c8ff1f914c6461ab70c8428b796c1"}, - {file = "wrapt-1.15.0-cp36-cp36m-win_amd64.whl", hash = "sha256:077ff0d1f9d9e4ce6476c1a924a3332452c1406e59d90a2cf24aeb29eeac9420"}, - {file = "wrapt-1.15.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:5c5aa28df055697d7c37d2099a7bc09f559d5053c3349b1ad0c39000e611d317"}, - {file = "wrapt-1.15.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3a8564f283394634a7a7054b7983e47dbf39c07712d7b177b37e03f2467a024e"}, - {file = "wrapt-1.15.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:780c82a41dc493b62fc5884fb1d3a3b81106642c5c5c78d6a0d4cbe96d62ba7e"}, - {file = "wrapt-1.15.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e169e957c33576f47e21864cf3fc9ff47c223a4ebca8960079b8bd36cb014fd0"}, - {file = "wrapt-1.15.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:b02f21c1e2074943312d03d243ac4388319f2456576b2c6023041c4d57cd7019"}, - {file = "wrapt-1.15.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:f2e69b3ed24544b0d3dbe2c5c0ba5153ce50dcebb576fdc4696d52aa22db6034"}, - {file = "wrapt-1.15.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d787272ed958a05b2c86311d3a4135d3c2aeea4fc655705f074130aa57d71653"}, - {file = "wrapt-1.15.0-cp37-cp37m-win32.whl", hash = "sha256:02fce1852f755f44f95af51f69d22e45080102e9d00258053b79367d07af39c0"}, - {file = "wrapt-1.15.0-cp37-cp37m-win_amd64.whl", hash = "sha256:abd52a09d03adf9c763d706df707c343293d5d106aea53483e0ec8d9e310ad5e"}, - {file = "wrapt-1.15.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:cdb4f085756c96a3af04e6eca7f08b1345e94b53af8921b25c72f096e704e145"}, - {file = "wrapt-1.15.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:230ae493696a371f1dbffaad3dafbb742a4d27a0afd2b1aecebe52b740167e7f"}, - {file = "wrapt-1.15.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:63424c681923b9f3bfbc5e3205aafe790904053d42ddcc08542181a30a7a51bd"}, - {file = "wrapt-1.15.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d6bcbfc99f55655c3d93feb7ef3800bd5bbe963a755687cbf1f490a71fb7794b"}, - {file = "wrapt-1.15.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c99f4309f5145b93eca6e35ac1a988f0dc0a7ccf9ccdcd78d3c0adf57224e62f"}, - {file = "wrapt-1.15.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:b130fe77361d6771ecf5a219d8e0817d61b236b7d8b37cc045172e574ed219e6"}, - {file = "wrapt-1.15.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:96177eb5645b1c6985f5c11d03fc2dbda9ad24ec0f3a46dcce91445747e15094"}, - {file = "wrapt-1.15.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:d5fe3e099cf07d0fb5a1e23d399e5d4d1ca3e6dfcbe5c8570ccff3e9208274f7"}, - {file = "wrapt-1.15.0-cp38-cp38-win32.whl", hash = "sha256:abd8f36c99512755b8456047b7be10372fca271bf1467a1caa88db991e7c421b"}, - {file = "wrapt-1.15.0-cp38-cp38-win_amd64.whl", hash = "sha256:b06fa97478a5f478fb05e1980980a7cdf2712015493b44d0c87606c1513ed5b1"}, - {file = "wrapt-1.15.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:2e51de54d4fb8fb50d6ee8327f9828306a959ae394d3e01a1ba8b2f937747d86"}, - {file = "wrapt-1.15.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0970ddb69bba00670e58955f8019bec4a42d1785db3faa043c33d81de2bf843c"}, - {file = "wrapt-1.15.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76407ab327158c510f44ded207e2f76b657303e17cb7a572ffe2f5a8a48aa04d"}, - {file = "wrapt-1.15.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cd525e0e52a5ff16653a3fc9e3dd827981917d34996600bbc34c05d048ca35cc"}, - {file = "wrapt-1.15.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9d37ac69edc5614b90516807de32d08cb8e7b12260a285ee330955604ed9dd29"}, - {file = "wrapt-1.15.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:078e2a1a86544e644a68422f881c48b84fef6d18f8c7a957ffd3f2e0a74a0d4a"}, - {file = "wrapt-1.15.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:2cf56d0e237280baed46f0b5316661da892565ff58309d4d2ed7dba763d984b8"}, - {file = "wrapt-1.15.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:7dc0713bf81287a00516ef43137273b23ee414fe41a3c14be10dd95ed98a2df9"}, - {file = "wrapt-1.15.0-cp39-cp39-win32.whl", hash = "sha256:46ed616d5fb42f98630ed70c3529541408166c22cdfd4540b88d5f21006b0eff"}, - {file = "wrapt-1.15.0-cp39-cp39-win_amd64.whl", hash = "sha256:eef4d64c650f33347c1f9266fa5ae001440b232ad9b98f1f43dfe7a79435c0a6"}, - {file = "wrapt-1.15.0-py3-none-any.whl", hash = "sha256:64b1df0f83706b4ef4cfb4fb0e4c2669100fd7ecacfb59e091fad300d4e04640"}, - {file = "wrapt-1.15.0.tar.gz", hash = "sha256:d06730c6aed78cee4126234cf2d071e01b44b915e725a6cb439a879ec9754a3a"}, + {file = "wrapt-1.16.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ffa565331890b90056c01db69c0fe634a776f8019c143a5ae265f9c6bc4bd6d4"}, + {file = "wrapt-1.16.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e4fdb9275308292e880dcbeb12546df7f3e0f96c6b41197e0cf37d2826359020"}, + {file = "wrapt-1.16.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bb2dee3874a500de01c93d5c71415fcaef1d858370d405824783e7a8ef5db440"}, + {file = "wrapt-1.16.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2a88e6010048489cda82b1326889ec075a8c856c2e6a256072b28eaee3ccf487"}, + {file = "wrapt-1.16.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ac83a914ebaf589b69f7d0a1277602ff494e21f4c2f743313414378f8f50a4cf"}, + {file = "wrapt-1.16.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:73aa7d98215d39b8455f103de64391cb79dfcad601701a3aa0dddacf74911d72"}, + {file = "wrapt-1.16.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:807cc8543a477ab7422f1120a217054f958a66ef7314f76dd9e77d3f02cdccd0"}, + {file = "wrapt-1.16.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:bf5703fdeb350e36885f2875d853ce13172ae281c56e509f4e6eca049bdfb136"}, + {file = "wrapt-1.16.0-cp310-cp310-win32.whl", hash = "sha256:f6b2d0c6703c988d334f297aa5df18c45e97b0af3679bb75059e0e0bd8b1069d"}, + {file = "wrapt-1.16.0-cp310-cp310-win_amd64.whl", hash = "sha256:decbfa2f618fa8ed81c95ee18a387ff973143c656ef800c9f24fb7e9c16054e2"}, + {file = "wrapt-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1a5db485fe2de4403f13fafdc231b0dbae5eca4359232d2efc79025527375b09"}, + {file = "wrapt-1.16.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:75ea7d0ee2a15733684badb16de6794894ed9c55aa5e9903260922f0482e687d"}, + {file = "wrapt-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a452f9ca3e3267cd4d0fcf2edd0d035b1934ac2bd7e0e57ac91ad6b95c0c6389"}, + {file = "wrapt-1.16.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:43aa59eadec7890d9958748db829df269f0368521ba6dc68cc172d5d03ed8060"}, + {file = "wrapt-1.16.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:72554a23c78a8e7aa02abbd699d129eead8b147a23c56e08d08dfc29cfdddca1"}, + {file = "wrapt-1.16.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:d2efee35b4b0a347e0d99d28e884dfd82797852d62fcd7ebdeee26f3ceb72cf3"}, + {file = "wrapt-1.16.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:6dcfcffe73710be01d90cae08c3e548d90932d37b39ef83969ae135d36ef3956"}, + {file = "wrapt-1.16.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:eb6e651000a19c96f452c85132811d25e9264d836951022d6e81df2fff38337d"}, + {file = "wrapt-1.16.0-cp311-cp311-win32.whl", hash = "sha256:66027d667efe95cc4fa945af59f92c5a02c6f5bb6012bff9e60542c74c75c362"}, + {file = "wrapt-1.16.0-cp311-cp311-win_amd64.whl", hash = "sha256:aefbc4cb0a54f91af643660a0a150ce2c090d3652cf4052a5397fb2de549cd89"}, + {file = "wrapt-1.16.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:5eb404d89131ec9b4f748fa5cfb5346802e5ee8836f57d516576e61f304f3b7b"}, + {file = "wrapt-1.16.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:9090c9e676d5236a6948330e83cb89969f433b1943a558968f659ead07cb3b36"}, + {file = "wrapt-1.16.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:94265b00870aa407bd0cbcfd536f17ecde43b94fb8d228560a1e9d3041462d73"}, + {file = "wrapt-1.16.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f2058f813d4f2b5e3a9eb2eb3faf8f1d99b81c3e51aeda4b168406443e8ba809"}, + {file = "wrapt-1.16.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:98b5e1f498a8ca1858a1cdbffb023bfd954da4e3fa2c0cb5853d40014557248b"}, + {file = "wrapt-1.16.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:14d7dc606219cdd7405133c713f2c218d4252f2a469003f8c46bb92d5d095d81"}, + {file = "wrapt-1.16.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:49aac49dc4782cb04f58986e81ea0b4768e4ff197b57324dcbd7699c5dfb40b9"}, + {file = "wrapt-1.16.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:418abb18146475c310d7a6dc71143d6f7adec5b004ac9ce08dc7a34e2babdc5c"}, + {file = "wrapt-1.16.0-cp312-cp312-win32.whl", hash = "sha256:685f568fa5e627e93f3b52fda002c7ed2fa1800b50ce51f6ed1d572d8ab3e7fc"}, + {file = "wrapt-1.16.0-cp312-cp312-win_amd64.whl", hash = "sha256:dcdba5c86e368442528f7060039eda390cc4091bfd1dca41e8046af7c910dda8"}, + {file = "wrapt-1.16.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:d462f28826f4657968ae51d2181a074dfe03c200d6131690b7d65d55b0f360f8"}, + {file = "wrapt-1.16.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a33a747400b94b6d6b8a165e4480264a64a78c8a4c734b62136062e9a248dd39"}, + {file = "wrapt-1.16.0-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b3646eefa23daeba62643a58aac816945cadc0afaf21800a1421eeba5f6cfb9c"}, + {file = "wrapt-1.16.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ebf019be5c09d400cf7b024aa52b1f3aeebeff51550d007e92c3c1c4afc2a40"}, + {file = "wrapt-1.16.0-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:0d2691979e93d06a95a26257adb7bfd0c93818e89b1406f5a28f36e0d8c1e1fc"}, + {file = "wrapt-1.16.0-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:1acd723ee2a8826f3d53910255643e33673e1d11db84ce5880675954183ec47e"}, + {file = "wrapt-1.16.0-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:bc57efac2da352a51cc4658878a68d2b1b67dbe9d33c36cb826ca449d80a8465"}, + {file = "wrapt-1.16.0-cp36-cp36m-win32.whl", hash = "sha256:da4813f751142436b075ed7aa012a8778aa43a99f7b36afe9b742d3ed8bdc95e"}, + {file = "wrapt-1.16.0-cp36-cp36m-win_amd64.whl", hash = "sha256:6f6eac2360f2d543cc875a0e5efd413b6cbd483cb3ad7ebf888884a6e0d2e966"}, + {file = "wrapt-1.16.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:a0ea261ce52b5952bf669684a251a66df239ec6d441ccb59ec7afa882265d593"}, + {file = "wrapt-1.16.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7bd2d7ff69a2cac767fbf7a2b206add2e9a210e57947dd7ce03e25d03d2de292"}, + {file = "wrapt-1.16.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9159485323798c8dc530a224bd3ffcf76659319ccc7bbd52e01e73bd0241a0c5"}, + {file = "wrapt-1.16.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a86373cf37cd7764f2201b76496aba58a52e76dedfaa698ef9e9688bfd9e41cf"}, + {file = "wrapt-1.16.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:73870c364c11f03ed072dda68ff7aea6d2a3a5c3fe250d917a429c7432e15228"}, + {file = "wrapt-1.16.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:b935ae30c6e7400022b50f8d359c03ed233d45b725cfdd299462f41ee5ffba6f"}, + {file = "wrapt-1.16.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:db98ad84a55eb09b3c32a96c576476777e87c520a34e2519d3e59c44710c002c"}, + {file = "wrapt-1.16.0-cp37-cp37m-win32.whl", hash = "sha256:9153ed35fc5e4fa3b2fe97bddaa7cbec0ed22412b85bcdaf54aeba92ea37428c"}, + {file = "wrapt-1.16.0-cp37-cp37m-win_amd64.whl", hash = "sha256:66dfbaa7cfa3eb707bbfcd46dab2bc6207b005cbc9caa2199bcbc81d95071a00"}, + {file = "wrapt-1.16.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1dd50a2696ff89f57bd8847647a1c363b687d3d796dc30d4dd4a9d1689a706f0"}, + {file = "wrapt-1.16.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:44a2754372e32ab315734c6c73b24351d06e77ffff6ae27d2ecf14cf3d229202"}, + {file = "wrapt-1.16.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8e9723528b9f787dc59168369e42ae1c3b0d3fadb2f1a71de14531d321ee05b0"}, + {file = "wrapt-1.16.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dbed418ba5c3dce92619656802cc5355cb679e58d0d89b50f116e4a9d5a9603e"}, + {file = "wrapt-1.16.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:941988b89b4fd6b41c3f0bfb20e92bd23746579736b7343283297c4c8cbae68f"}, + {file = "wrapt-1.16.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:6a42cd0cfa8ffc1915aef79cb4284f6383d8a3e9dcca70c445dcfdd639d51267"}, + {file = "wrapt-1.16.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:1ca9b6085e4f866bd584fb135a041bfc32cab916e69f714a7d1d397f8c4891ca"}, + {file = "wrapt-1.16.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:d5e49454f19ef621089e204f862388d29e6e8d8b162efce05208913dde5b9ad6"}, + {file = "wrapt-1.16.0-cp38-cp38-win32.whl", hash = "sha256:c31f72b1b6624c9d863fc095da460802f43a7c6868c5dda140f51da24fd47d7b"}, + {file = "wrapt-1.16.0-cp38-cp38-win_amd64.whl", hash = "sha256:490b0ee15c1a55be9c1bd8609b8cecd60e325f0575fc98f50058eae366e01f41"}, + {file = "wrapt-1.16.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9b201ae332c3637a42f02d1045e1d0cccfdc41f1f2f801dafbaa7e9b4797bfc2"}, + {file = "wrapt-1.16.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:2076fad65c6736184e77d7d4729b63a6d1ae0b70da4868adeec40989858eb3fb"}, + {file = "wrapt-1.16.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c5cd603b575ebceca7da5a3a251e69561bec509e0b46e4993e1cac402b7247b8"}, + {file = "wrapt-1.16.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b47cfad9e9bbbed2339081f4e346c93ecd7ab504299403320bf85f7f85c7d46c"}, + {file = "wrapt-1.16.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f8212564d49c50eb4565e502814f694e240c55551a5f1bc841d4fcaabb0a9b8a"}, + {file = "wrapt-1.16.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:5f15814a33e42b04e3de432e573aa557f9f0f56458745c2074952f564c50e664"}, + {file = "wrapt-1.16.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:db2e408d983b0e61e238cf579c09ef7020560441906ca990fe8412153e3b291f"}, + {file = "wrapt-1.16.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:edfad1d29c73f9b863ebe7082ae9321374ccb10879eeabc84ba3b69f2579d537"}, + {file = "wrapt-1.16.0-cp39-cp39-win32.whl", hash = "sha256:ed867c42c268f876097248e05b6117a65bcd1e63b779e916fe2e33cd6fd0d3c3"}, + {file = "wrapt-1.16.0-cp39-cp39-win_amd64.whl", hash = "sha256:eb1b046be06b0fce7249f1d025cd359b4b80fc1c3e24ad9eca33e0dcdb2e4a35"}, + {file = "wrapt-1.16.0-py3-none-any.whl", hash = "sha256:6906c4100a8fcbf2fa735f6059214bb13b97f75b1a61777fcf6432121ef12ef1"}, + {file = "wrapt-1.16.0.tar.gz", hash = "sha256:5f370f952971e7d17c7d1ead40e49f32345a7f7a5373571ef44d800d06b1899d"}, ] [[package]] @@ -3504,4 +3514,4 @@ virustotal = ["validators"] [metadata] lock-version = "2.0" python-versions = "^3.8" -content-hash = "7aa52b25c8e8ee932fe7e405a814040e6080ff88fa5c854d0505cb40407afb41" +content-hash = "503b5b6e7bdfb1151e543cc487192595798f831e006317165c19aa1177e9356f" diff --git a/pyproject.toml b/pyproject.toml index 3c01e8c..a28bf24 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -53,11 +53,11 @@ pydeep2 = {version = "^0.5.1", optional = true} lief = {version = "^0.13.2", optional = true} beautifulsoup4 = {version = "^4.12.2", optional = true} validators = {version = "^0.22.0", optional = true} -sphinx-autodoc-typehints = {version = "^1.24.1", optional = true} +sphinx-autodoc-typehints = {version = "^1.25.2", optional = true} recommonmark = {version = "^0.7.1", optional = true} -reportlab = {version = "^4.0.6", optional = true} +reportlab = {version = "^4.0.7", optional = true} pyfaup = {version = "^1.2", optional = true} -publicsuffixlist = {version = "^0.10.0.20231104", optional = true} +publicsuffixlist = {version = "^0.10.0.20231109", optional = true} urllib3 = {extras = ["brotli"], version = "*", optional = true} Sphinx = [ {version = "<7.2", python = "<3.9", optional = true}, @@ -76,7 +76,7 @@ brotli = ['urllib3'] [tool.poetry.group.dev.dependencies] requests-mock = "^1.11.0" -mypy = "^1.6.1" +mypy = "^1.7.0" ipython = [ {version = "<8.13.0", python = "<3.9"}, {version = "^8.13.0", python = ">=3.9"} @@ -84,7 +84,7 @@ ipython = [ jupyterlab = "^4.0.8" types-requests = "^2.31.0.10" types-python-dateutil = "^2.8.19.14" -types-redis = "^4.6.0.9" +types-redis = "^4.6.0.10" types-Flask = "^1.1.6" pytest-cov = "^4.1.0" From 4270e97ccebe89f6b2df0bdea1bd32aa04641a07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Vinot?= Date: Fri, 17 Nov 2023 12:52:05 +0100 Subject: [PATCH 03/80] chg: Bump deps --- poetry.lock | 267 +++++++++++++++++++++++-------------------------- pyproject.toml | 2 +- 2 files changed, 126 insertions(+), 143 deletions(-) diff --git a/poetry.lock b/poetry.lock index 9386f66..015e598 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.7.0 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.7.1 and should not be changed by hand. [[package]] name = "alabaster" @@ -870,39 +870,40 @@ tests = ["asttokens (>=2.1.0)", "coverage", "coverage-enable-subprocess", "ipyth [[package]] name = "extract-msg" -version = "0.45.0" +version = "0.46.2" description = "Extracts emails and attachments saved in Microsoft Outlook's .msg files" optional = true python-versions = ">=3.8" files = [ - {file = "extract_msg-0.45.0-py2.py3-none-any.whl", hash = "sha256:af645ffe1534bce93b20390576dac2aee027c17a714365172d31b3894f810ca7"}, - {file = "extract_msg-0.45.0.tar.gz", hash = "sha256:6814865cf2ba806bd69af53af688a13e000a95d4991cce6a0416b3bdeb739496"}, + {file = "extract_msg-0.46.2-py2.py3-none-any.whl", hash = "sha256:f49e530d16ac3e89c1d954d03b9bf03e2703a86fdd640fc3c56f1b41024c74f6"}, + {file = "extract_msg-0.46.2.tar.gz", hash = "sha256:1ccc852881bba973a1f2e2b65e72138aaf2b5784dddc13be34d65af1c410e8ab"}, ] [package.dependencies] beautifulsoup4 = ">=4.11.1,<4.13" compressed-rtf = ">=1.0.6,<2" ebcdic = ">=1.1.1,<2" -imapclient = ">=2.3.0,<3" olefile = "0.46" red-black-tree-mod = "1.20" RTFDE = ">=0.1.0,<0.2" tzlocal = ">=4.2,<6" [package.extras] -all = ["extract-msg[image]", "extract-msg[mime]"] +all = ["extract-msg[encoding]", "extract-msg[image]", "extract-msg[mime]"] +encoding = ["chardet (>=3.0.0,<6)"] image = ["Pillow (>=9.5.0,<10)"] mime = ["python-magic (>=0.4.27,<0.5)"] +readthedocs = ["sphinx-rtd-theme"] [[package]] name = "fastjsonschema" -version = "2.18.1" +version = "2.19.0" description = "Fastest Python implementation of JSON schema" optional = false python-versions = "*" files = [ - {file = "fastjsonschema-2.18.1-py3-none-any.whl", hash = "sha256:aec6a19e9f66e9810ab371cc913ad5f4e9e479b63a7072a2cd060a9369e329a8"}, - {file = "fastjsonschema-2.18.1.tar.gz", hash = "sha256:06dc8680d937628e993fa0cd278f196d20449a1adc087640710846b324d422ea"}, + {file = "fastjsonschema-2.19.0-py3-none-any.whl", hash = "sha256:b9fd1a2dd6971dbc7fee280a95bd199ae0dd9ce22beb91cc75e9c1c528a5170e"}, + {file = "fastjsonschema-2.19.0.tar.gz", hash = "sha256:e25df6647e1bc4a26070b700897b07b542ec898dd4f1f6ea013e7f6a88417225"}, ] [package.extras] @@ -941,24 +942,6 @@ files = [ {file = "imagesize-1.4.1.tar.gz", hash = "sha256:69150444affb9cb0d5cc5a92b3676f0b2fb7cd9ae39e947a5e11a36b4497cd4a"}, ] -[[package]] -name = "imapclient" -version = "2.3.1" -description = "Easy-to-use, Pythonic and complete IMAP client library" -optional = true -python-versions = "*" -files = [ - {file = "IMAPClient-2.3.1-py2.py3-none-any.whl", hash = "sha256:057f28025d2987c63e065afb0e4370b0b850b539b0e1494cea0427e88130108c"}, - {file = "IMAPClient-2.3.1.zip", hash = "sha256:26ea995664fae3a88b878ebce2aff7402931697b86658b7882043ddb01b0e6ba"}, -] - -[package.dependencies] -six = "*" - -[package.extras] -doc = ["sphinx"] -test = ["mock (>=1.3.0)"] - [[package]] name = "importlib-metadata" version = "6.8.0" @@ -1193,13 +1176,13 @@ files = [ [[package]] name = "jsonschema" -version = "4.19.2" +version = "4.20.0" description = "An implementation of JSON Schema validation for Python" optional = false python-versions = ">=3.8" files = [ - {file = "jsonschema-4.19.2-py3-none-any.whl", hash = "sha256:eee9e502c788e89cb166d4d37f43084e3b64ab405c795c03d343a4dbc2c810fc"}, - {file = "jsonschema-4.19.2.tar.gz", hash = "sha256:c9ff4d7447eed9592c23a12ccee508baf0dd0d59650615e847feb6cdca74f392"}, + {file = "jsonschema-4.20.0-py3-none-any.whl", hash = "sha256:ed6231f0429ecf966f5bc8dfef245998220549cbbcf140f913b7464c52c3b6b3"}, + {file = "jsonschema-4.20.0.tar.gz", hash = "sha256:4f614fd46d8d61258610998997743ec5492a648b33cf478c1ddc23ed4598a5fa"}, ] [package.dependencies] @@ -1224,18 +1207,18 @@ format-nongpl = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339- [[package]] name = "jsonschema-specifications" -version = "2023.7.1" +version = "2023.11.1" description = "The JSON Schema meta-schemas and vocabularies, exposed as a Registry" optional = false python-versions = ">=3.8" files = [ - {file = "jsonschema_specifications-2023.7.1-py3-none-any.whl", hash = "sha256:05adf340b659828a004220a9613be00fa3f223f2b82002e273dee62fd50524b1"}, - {file = "jsonschema_specifications-2023.7.1.tar.gz", hash = "sha256:c91a50404e88a1f6ba40636778e2ee08f6e24c5613fe4c53ac24578a5a7f72bb"}, + {file = "jsonschema_specifications-2023.11.1-py3-none-any.whl", hash = "sha256:f596778ab612b3fd29f72ea0d990393d0540a5aab18bf0407a46632eab540779"}, + {file = "jsonschema_specifications-2023.11.1.tar.gz", hash = "sha256:c9b234904ffe02f079bf91b14d79987faa685fd4b39c377a0996954c0090b9ca"}, ] [package.dependencies] importlib-resources = {version = ">=1.4.0", markers = "python_version < \"3.9\""} -referencing = ">=0.28.0" +referencing = ">=0.31.0" [[package]] name = "jupyter-client" @@ -1322,13 +1305,13 @@ jupyter-server = ">=1.1.2" [[package]] name = "jupyter-server" -version = "2.10.0" +version = "2.10.1" description = "The backend—i.e. core services, APIs, and REST endpoints—to Jupyter web applications." optional = false python-versions = ">=3.8" files = [ - {file = "jupyter_server-2.10.0-py3-none-any.whl", hash = "sha256:dde56c9bc3cb52d7b72cc0f696d15d7163603526f1a758eb4a27405b73eab2a5"}, - {file = "jupyter_server-2.10.0.tar.gz", hash = "sha256:47b8f5e63440125cb1bb8957bf12b18453ee5ed9efe42d2f7b2ca66a7019a278"}, + {file = "jupyter_server-2.10.1-py3-none-any.whl", hash = "sha256:20519e355d951fc5e1b6ac5952854fe7620d0cfb56588fa4efe362a758977ed3"}, + {file = "jupyter_server-2.10.1.tar.gz", hash = "sha256:e6da2657a954a7879eed28cc08e0817b01ffd81d7eab8634660397b55f926472"}, ] [package.dependencies] @@ -1337,7 +1320,7 @@ argon2-cffi = "*" jinja2 = "*" jupyter-client = ">=7.4.4" jupyter-core = ">=4.12,<5.0.dev0 || >=5.1.dev0" -jupyter-events = ">=0.6.0" +jupyter-events = ">=0.9.0" jupyter-server-terminals = "*" nbconvert = ">=6.4.4" nbformat = ">=5.3.0" @@ -2459,13 +2442,13 @@ files = [ [[package]] name = "referencing" -version = "0.30.2" +version = "0.31.0" description = "JSON Referencing + Python" optional = false python-versions = ">=3.8" files = [ - {file = "referencing-0.30.2-py3-none-any.whl", hash = "sha256:449b6669b6121a9e96a7f9e410b245d471e8d48964c67113ce9afe50c8dd7bdf"}, - {file = "referencing-0.30.2.tar.gz", hash = "sha256:794ad8003c65938edcdbc027f1933215e0d0ccc0291e3ce20a4d87432b59efc0"}, + {file = "referencing-0.31.0-py3-none-any.whl", hash = "sha256:381b11e53dd93babb55696c71cf42aef2d36b8a150c49bf0bc301e36d536c882"}, + {file = "referencing-0.31.0.tar.gz", hash = "sha256:cc28f2c88fbe7b961a7817a0abc034c09a1e36358f82fedb4ffdf29a25398863"}, ] [package.dependencies] @@ -2558,110 +2541,110 @@ files = [ [[package]] name = "rpds-py" -version = "0.12.0" +version = "0.13.0" description = "Python bindings to Rust's persistent data structures (rpds)" optional = false python-versions = ">=3.8" files = [ - {file = "rpds_py-0.12.0-cp310-cp310-macosx_10_7_x86_64.whl", hash = "sha256:c694bee70ece3b232df4678448fdda245fd3b1bb4ba481fb6cd20e13bb784c46"}, - {file = "rpds_py-0.12.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:30e5ce9f501fb1f970e4a59098028cf20676dee64fc496d55c33e04bbbee097d"}, - {file = "rpds_py-0.12.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d72a4315514e5a0b9837a086cb433b004eea630afb0cc129de76d77654a9606f"}, - {file = "rpds_py-0.12.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:eebaf8c76c39604d52852366249ab807fe6f7a3ffb0dd5484b9944917244cdbe"}, - {file = "rpds_py-0.12.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a239303acb0315091d54c7ff36712dba24554993b9a93941cf301391d8a997ee"}, - {file = "rpds_py-0.12.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ced40cdbb6dd47a032725a038896cceae9ce267d340f59508b23537f05455431"}, - {file = "rpds_py-0.12.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3c8c0226c71bd0ce9892eaf6afa77ae8f43a3d9313124a03df0b389c01f832de"}, - {file = "rpds_py-0.12.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b8e11715178f3608874508f08e990d3771e0b8c66c73eb4e183038d600a9b274"}, - {file = "rpds_py-0.12.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:5210a0018c7e09c75fa788648617ebba861ae242944111d3079034e14498223f"}, - {file = "rpds_py-0.12.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:171d9a159f1b2f42a42a64a985e4ba46fc7268c78299272ceba970743a67ee50"}, - {file = "rpds_py-0.12.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:57ec6baec231bb19bb5fd5fc7bae21231860a1605174b11585660236627e390e"}, - {file = "rpds_py-0.12.0-cp310-none-win32.whl", hash = "sha256:7188ddc1a8887194f984fa4110d5a3d5b9b5cd35f6bafdff1b649049cbc0ce29"}, - {file = "rpds_py-0.12.0-cp310-none-win_amd64.whl", hash = "sha256:1e04581c6117ad9479b6cfae313e212fe0dfa226ac727755f0d539cd54792963"}, - {file = "rpds_py-0.12.0-cp311-cp311-macosx_10_7_x86_64.whl", hash = "sha256:0a38612d07a36138507d69646c470aedbfe2b75b43a4643f7bd8e51e52779624"}, - {file = "rpds_py-0.12.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f12d69d568f5647ec503b64932874dade5a20255736c89936bf690951a5e79f5"}, - {file = "rpds_py-0.12.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4f8a1d990dc198a6c68ec3d9a637ba1ce489b38cbfb65440a27901afbc5df575"}, - {file = "rpds_py-0.12.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8c567c664fc2f44130a20edac73e0a867f8e012bf7370276f15c6adc3586c37c"}, - {file = "rpds_py-0.12.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0e9e976e0dbed4f51c56db10831c9623d0fd67aac02853fe5476262e5a22acb7"}, - {file = "rpds_py-0.12.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:efddca2d02254a52078c35cadad34762adbae3ff01c6b0c7787b59d038b63e0d"}, - {file = "rpds_py-0.12.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d9e7f29c00577aff6b318681e730a519b235af292732a149337f6aaa4d1c5e31"}, - {file = "rpds_py-0.12.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:389c0e38358fdc4e38e9995e7291269a3aead7acfcf8942010ee7bc5baee091c"}, - {file = "rpds_py-0.12.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:33ab498f9ac30598b6406e2be1b45fd231195b83d948ebd4bd77f337cb6a2bff"}, - {file = "rpds_py-0.12.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:d56b1cd606ba4cedd64bb43479d56580e147c6ef3f5d1c5e64203a1adab784a2"}, - {file = "rpds_py-0.12.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1fa73ed22c40a1bec98d7c93b5659cd35abcfa5a0a95ce876b91adbda170537c"}, - {file = "rpds_py-0.12.0-cp311-none-win32.whl", hash = "sha256:dbc25baa6abb205766fb8606f8263b02c3503a55957fcb4576a6bb0a59d37d10"}, - {file = "rpds_py-0.12.0-cp311-none-win_amd64.whl", hash = "sha256:c6b52b7028b547866c2413f614ee306c2d4eafdd444b1ff656bf3295bf1484aa"}, - {file = "rpds_py-0.12.0-cp312-cp312-macosx_10_7_x86_64.whl", hash = "sha256:9620650c364c01ed5b497dcae7c3d4b948daeae6e1883ae185fef1c927b6b534"}, - {file = "rpds_py-0.12.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2124f9e645a94ab7c853bc0a3644e0ca8ffbe5bb2d72db49aef8f9ec1c285733"}, - {file = "rpds_py-0.12.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:281c8b219d4f4b3581b918b816764098d04964915b2f272d1476654143801aa2"}, - {file = "rpds_py-0.12.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:27ccc93c7457ef890b0dd31564d2a05e1aca330623c942b7e818e9e7c2669ee4"}, - {file = "rpds_py-0.12.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d1c562a9bb72244fa767d1c1ab55ca1d92dd5f7c4d77878fee5483a22ffac808"}, - {file = "rpds_py-0.12.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e57919c32ee295a2fca458bb73e4b20b05c115627f96f95a10f9f5acbd61172d"}, - {file = "rpds_py-0.12.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fa35ad36440aaf1ac8332b4a4a433d4acd28f1613f0d480995f5cfd3580e90b7"}, - {file = "rpds_py-0.12.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e6aea5c0eb5b0faf52c7b5c4a47c8bb64437173be97227c819ffa31801fa4e34"}, - {file = "rpds_py-0.12.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:81cf9d306c04df1b45971c13167dc3bad625808aa01281d55f3cf852dde0e206"}, - {file = "rpds_py-0.12.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:08e6e7ff286254016b945e1ab632ee843e43d45e40683b66dd12b73791366dd1"}, - {file = "rpds_py-0.12.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:4d0a675a7acbbc16179188d8c6d0afb8628604fc1241faf41007255957335a0b"}, - {file = "rpds_py-0.12.0-cp312-none-win32.whl", hash = "sha256:b2287c09482949e0ca0c0eb68b2aca6cf57f8af8c6dfd29dcd3bc45f17b57978"}, - {file = "rpds_py-0.12.0-cp312-none-win_amd64.whl", hash = "sha256:8015835494b21aa7abd3b43fdea0614ee35ef6b03db7ecba9beb58eadf01c24f"}, - {file = "rpds_py-0.12.0-cp38-cp38-macosx_10_7_x86_64.whl", hash = "sha256:6174d6ad6b58a6bcf67afbbf1723420a53d06c4b89f4c50763d6fa0a6ac9afd2"}, - {file = "rpds_py-0.12.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:a689e1ded7137552bea36305a7a16ad2b40be511740b80748d3140614993db98"}, - {file = "rpds_py-0.12.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f45321224144c25a62052035ce96cbcf264667bcb0d81823b1bbc22c4addd194"}, - {file = "rpds_py-0.12.0-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:aa32205358a76bf578854bf31698a86dc8b2cb591fd1d79a833283f4a403f04b"}, - {file = "rpds_py-0.12.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:91bd2b7cf0f4d252eec8b7046fa6a43cee17e8acdfc00eaa8b3dbf2f9a59d061"}, - {file = "rpds_py-0.12.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3acadbab8b59f63b87b518e09c4c64b142e7286b9ca7a208107d6f9f4c393c5c"}, - {file = "rpds_py-0.12.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:429349a510da82c85431f0f3e66212d83efe9fd2850f50f339341b6532c62fe4"}, - {file = "rpds_py-0.12.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:05942656cb2cb4989cd50ced52df16be94d344eae5097e8583966a1d27da73a5"}, - {file = "rpds_py-0.12.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:0c5441b7626c29dbd54a3f6f3713ec8e956b009f419ffdaaa3c80eaf98ddb523"}, - {file = "rpds_py-0.12.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:b6b0e17d39d21698185097652c611f9cf30f7c56ccec189789920e3e7f1cee56"}, - {file = "rpds_py-0.12.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:3b7a64d43e2a1fa2dd46b678e00cabd9a49ebb123b339ce799204c44a593ae1c"}, - {file = "rpds_py-0.12.0-cp38-none-win32.whl", hash = "sha256:e5bbe011a2cea9060fef1bb3d668a2fd8432b8888e6d92e74c9c794d3c101595"}, - {file = "rpds_py-0.12.0-cp38-none-win_amd64.whl", hash = "sha256:bec29b801b4adbf388314c0d050e851d53762ab424af22657021ce4b6eb41543"}, - {file = "rpds_py-0.12.0-cp39-cp39-macosx_10_7_x86_64.whl", hash = "sha256:1096ca0bf2d3426cbe79d4ccc91dc5aaa73629b08ea2d8467375fad8447ce11a"}, - {file = "rpds_py-0.12.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:48aa98987d54a46e13e6954880056c204700c65616af4395d1f0639eba11764b"}, - {file = "rpds_py-0.12.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7979d90ee2190d000129598c2b0c82f13053dba432b94e45e68253b09bb1f0f6"}, - {file = "rpds_py-0.12.0-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:88857060b690a57d2ea8569bca58758143c8faa4639fb17d745ce60ff84c867e"}, - {file = "rpds_py-0.12.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4eb74d44776b0fb0782560ea84d986dffec8ddd94947f383eba2284b0f32e35e"}, - {file = "rpds_py-0.12.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f62581d7e884dd01ee1707b7c21148f61f2febb7de092ae2f108743fcbef5985"}, - {file = "rpds_py-0.12.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6f5dcb658d597410bb7c967c1d24eaf9377b0d621358cbe9d2ff804e5dd12e81"}, - {file = "rpds_py-0.12.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9bf9acce44e967a5103fcd820fc7580c7b0ab8583eec4e2051aec560f7b31a63"}, - {file = "rpds_py-0.12.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:240687b5be0f91fbde4936a329c9b7589d9259742766f74de575e1b2046575e4"}, - {file = "rpds_py-0.12.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:25740fb56e8bd37692ed380e15ec734be44d7c71974d8993f452b4527814601e"}, - {file = "rpds_py-0.12.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:a54917b7e9cd3a67e429a630e237a90b096e0ba18897bfb99ee8bd1068a5fea0"}, - {file = "rpds_py-0.12.0-cp39-none-win32.whl", hash = "sha256:b92aafcfab3d41580d54aca35a8057341f1cfc7c9af9e8bdfc652f83a20ced31"}, - {file = "rpds_py-0.12.0-cp39-none-win_amd64.whl", hash = "sha256:cd316dbcc74c76266ba94eb021b0cc090b97cca122f50bd7a845f587ff4bf03f"}, - {file = "rpds_py-0.12.0-pp310-pypy310_pp73-macosx_10_7_x86_64.whl", hash = "sha256:0853da3d5e9bc6a07b2486054a410b7b03f34046c123c6561b535bb48cc509e1"}, - {file = "rpds_py-0.12.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:cb41ad20064e18a900dd427d7cf41cfaec83bcd1184001f3d91a1f76b3fcea4e"}, - {file = "rpds_py-0.12.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b710bf7e7ae61957d5c4026b486be593ed3ec3dca3e5be15e0f6d8cf5d0a4990"}, - {file = "rpds_py-0.12.0-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a952ae3eb460c6712388ac2ec706d24b0e651b9396d90c9a9e0a69eb27737fdc"}, - {file = "rpds_py-0.12.0-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0bedd91ae1dd142a4dc15970ed2c729ff6c73f33a40fa84ed0cdbf55de87c777"}, - {file = "rpds_py-0.12.0-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:761531076df51309075133a6bc1db02d98ec7f66e22b064b1d513bc909f29743"}, - {file = "rpds_py-0.12.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a2baa6be130e8a00b6cbb9f18a33611ec150b4537f8563bddadb54c1b74b8193"}, - {file = "rpds_py-0.12.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f05450fa1cd7c525c0b9d1a7916e595d3041ac0afbed2ff6926e5afb6a781b7f"}, - {file = "rpds_py-0.12.0-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:81c4d1a3a564775c44732b94135d06e33417e829ff25226c164664f4a1046213"}, - {file = "rpds_py-0.12.0-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:e888be685fa42d8b8a3d3911d5604d14db87538aa7d0b29b1a7ea80d354c732d"}, - {file = "rpds_py-0.12.0-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:6f8d7fe73d1816eeb5378409adc658f9525ecbfaf9e1ede1e2d67a338b0c7348"}, - {file = "rpds_py-0.12.0-pp38-pypy38_pp73-macosx_10_7_x86_64.whl", hash = "sha256:0831d3ecdea22e4559cc1793f22e77067c9d8c451d55ae6a75bf1d116a8e7f42"}, - {file = "rpds_py-0.12.0-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:513ccbf7420c30e283c25c82d5a8f439d625a838d3ba69e79a110c260c46813f"}, - {file = "rpds_py-0.12.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:301bd744a1adaa2f6a5e06c98f1ac2b6f8dc31a5c23b838f862d65e32fca0d4b"}, - {file = "rpds_py-0.12.0-pp38-pypy38_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f8832a4f83d4782a8f5a7b831c47e8ffe164e43c2c148c8160ed9a6d630bc02a"}, - {file = "rpds_py-0.12.0-pp38-pypy38_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4b2416ed743ec5debcf61e1242e012652a4348de14ecc7df3512da072b074440"}, - {file = "rpds_py-0.12.0-pp38-pypy38_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:35585a8cb5917161f42c2104567bb83a1d96194095fc54a543113ed5df9fa436"}, - {file = "rpds_py-0.12.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d389ff1e95b6e46ebedccf7fd1fadd10559add595ac6a7c2ea730268325f832c"}, - {file = "rpds_py-0.12.0-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9b007c2444705a2dc4a525964fd4dd28c3320b19b3410da6517cab28716f27d3"}, - {file = "rpds_py-0.12.0-pp38-pypy38_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:188912b22b6c8225f4c4ffa020a2baa6ad8fabb3c141a12dbe6edbb34e7f1425"}, - {file = "rpds_py-0.12.0-pp38-pypy38_pp73-musllinux_1_2_i686.whl", hash = "sha256:1b4cf9ab9a0ae0cb122685209806d3f1dcb63b9fccdf1424fb42a129dc8c2faa"}, - {file = "rpds_py-0.12.0-pp38-pypy38_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:2d34a5450a402b00d20aeb7632489ffa2556ca7b26f4a63c35f6fccae1977427"}, - {file = "rpds_py-0.12.0-pp39-pypy39_pp73-macosx_10_7_x86_64.whl", hash = "sha256:466030a42724780794dea71eb32db83cc51214d66ab3fb3156edd88b9c8f0d78"}, - {file = "rpds_py-0.12.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:68172622a5a57deb079a2c78511c40f91193548e8ab342c31e8cb0764d362459"}, - {file = "rpds_py-0.12.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:54cdfcda59251b9c2f87a05d038c2ae02121219a04d4a1e6fc345794295bdc07"}, - {file = "rpds_py-0.12.0-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6b75b912a0baa033350367a8a07a8b2d44fd5b90c890bfbd063a8a5f945f644b"}, - {file = "rpds_py-0.12.0-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:47aeceb4363851d17f63069318ba5721ae695d9da55d599b4d6fb31508595278"}, - {file = "rpds_py-0.12.0-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0525847f83f506aa1e28eb2057b696fe38217e12931c8b1b02198cfe6975e142"}, - {file = "rpds_py-0.12.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:efbe0b5e0fd078ed7b005faa0170da4f72666360f66f0bb2d7f73526ecfd99f9"}, - {file = "rpds_py-0.12.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:0fadfdda275c838cba5102c7f90a20f2abd7727bf8f4a2b654a5b617529c5c18"}, - {file = "rpds_py-0.12.0-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:56dd500411d03c5e9927a1eb55621e906837a83b02350a9dc401247d0353717c"}, - {file = "rpds_py-0.12.0-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:6915fc9fa6b3ec3569566832e1bb03bd801c12cea030200e68663b9a87974e76"}, - {file = "rpds_py-0.12.0-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:5f1519b080d8ce0a814f17ad9fb49fb3a1d4d7ce5891f5c85fc38631ca3a8dc4"}, - {file = "rpds_py-0.12.0.tar.gz", hash = "sha256:7036316cc26b93e401cedd781a579be606dad174829e6ad9e9c5a0da6e036f80"}, + {file = "rpds_py-0.13.0-cp310-cp310-macosx_10_7_x86_64.whl", hash = "sha256:1758197cc8d7ff383c07405f188253535b4aa7fa745cbc54d221ae84b18e0702"}, + {file = "rpds_py-0.13.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:715df74cbcef4387d623c917f295352127f4b3e0388038d68fa577b4e4c6e540"}, + {file = "rpds_py-0.13.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c8a9cec0f49df9bac252d92f138c0d7708d98828e21fd57db78087d8f50b5656"}, + {file = "rpds_py-0.13.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5c2545bba02f68abdf398ef4990dc77592cc1e5d29438b35b3a3ca34d171fb4b"}, + {file = "rpds_py-0.13.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:95375c44ffb9ea2bc25d67fb66e726ea266ff1572df50b9556fe28a5f3519cd7"}, + {file = "rpds_py-0.13.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:54e513df45a8a9419e7952ffd26ac9a5b7b1df97fe72530421794b0de29f9d72"}, + {file = "rpds_py-0.13.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a25f514a53927b6b4bd04a9a6a13b55209df54f548660eeed673336c0c946d14"}, + {file = "rpds_py-0.13.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c1a920fa679ec2758411d66bf68840b0a21317b9954ab0e973742d723bb67709"}, + {file = "rpds_py-0.13.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:f9339d1404b87e6d8cb35e485945753be57a99ab9bb389f42629215b2f6bda0f"}, + {file = "rpds_py-0.13.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:c99f9dda2c959f7bb69a7125e192c74fcafb7a534a95ccf49313ae3a04807804"}, + {file = "rpds_py-0.13.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:bad6758df5f1042b35683bd1811d5432ac1b17700a5a2a51fdc293f7df5f7827"}, + {file = "rpds_py-0.13.0-cp310-none-win32.whl", hash = "sha256:2a29ec68fa9655ce9501bc6ae074b166e8b45c2dfcd2d71d90d1a61758ed8c73"}, + {file = "rpds_py-0.13.0-cp310-none-win_amd64.whl", hash = "sha256:244be953f13f148b0071d67a610f89cd72eb5013a147e517d6ca3f3f3b7e0380"}, + {file = "rpds_py-0.13.0-cp311-cp311-macosx_10_7_x86_64.whl", hash = "sha256:240279ca0b2afd6d4710afce1c94bf9e75fc161290bf62c0feba64d64780d80b"}, + {file = "rpds_py-0.13.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:25c9727da2dabc93664a18eda7a70feedf478f0c4c8294e4cdba7f60a479a246"}, + {file = "rpds_py-0.13.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:981e46e1e5064f95460381bff4353783b4b5ce351c930e5b507ebe0278c61dac"}, + {file = "rpds_py-0.13.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6052bb47ea583646b8ff562acacb9a2ec5ec847267049cbae3919671929e94c6"}, + {file = "rpds_py-0.13.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:87f591ff8cc834fa01ca5899ab5edcd7ee590492a9cdcf43424ac142e731ce3e"}, + {file = "rpds_py-0.13.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:62772259b3381e2aabf274c74fd1e1ac03b0524de0a6593900684becfa8cfe4b"}, + {file = "rpds_py-0.13.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b4de9d20fe68c16b4d97f551a09920745add0c86430262230528b83c2ed2fe90"}, + {file = "rpds_py-0.13.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b70a54fb628c1d6400e351674a31ba63d2912b8c5b707f99b408674a5d8b69ab"}, + {file = "rpds_py-0.13.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:2063ab9cd1be7ef6b5ed0f408e2bdf32c060b6f40c097a468f32864731302636"}, + {file = "rpds_py-0.13.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:84f7f3f18d29a1c645729634003d21d84028bd9c2fd78eba9d028998f46fa5aa"}, + {file = "rpds_py-0.13.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f7c7ddc8d1a64623068da5a15e28001fbd0f0aff754aae7a75a4be5042191638"}, + {file = "rpds_py-0.13.0-cp311-none-win32.whl", hash = "sha256:8a33d2b6340261191bb59adb5a453fa6c7d99de85552bd4e8196411f0509c9bf"}, + {file = "rpds_py-0.13.0-cp311-none-win_amd64.whl", hash = "sha256:8b9c1dd90461940315981499df62a627571c4f0992e8bafc5396d33916224cac"}, + {file = "rpds_py-0.13.0-cp312-cp312-macosx_10_7_x86_64.whl", hash = "sha256:15a2d542de5cbfc6abddc4846d9412b59f8ee9c8dfa0b9c92a29321297c91745"}, + {file = "rpds_py-0.13.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8dd69e01b29ff45a0062cad5c480d8aa9301c3ef09da471f86337a78eb2d3405"}, + {file = "rpds_py-0.13.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:efdd02971a02f98492a72b25484f1f6125fb9f2166e48cc4c9bfa563349c851b"}, + {file = "rpds_py-0.13.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:91ca9aaee7ccdfa66d800b5c4ec634fefca947721bab52d6ad2f6350969a3771"}, + {file = "rpds_py-0.13.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:afcec1f5b09d0db70aeb2d90528a9164acb61841a3124e28f6ac0137f4c36cb4"}, + {file = "rpds_py-0.13.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5c6824673f66c47f7ee759c21e973bfce3ceaf2c25cb940cb45b41105dc914e8"}, + {file = "rpds_py-0.13.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:50b6d80925dfeb573fc5e38582fb9517c6912dc462cc858a11c8177b0837127a"}, + {file = "rpds_py-0.13.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:3a1a38512925829784b5dc38591c757b80cfce115c72c594dc59567dab62b9c4"}, + {file = "rpds_py-0.13.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:977c6123c359dcc70ce3161b781ab70b0d342de2666944b776617e01a0a7822a"}, + {file = "rpds_py-0.13.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:c472409037e05ed87b99430f97a6b82130328bb977502813547e8ee6a3392502"}, + {file = "rpds_py-0.13.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:28bb22019f4a783ea06a6b81437d5996551869e8a722ee8720b744f7684d97f4"}, + {file = "rpds_py-0.13.0-cp312-none-win32.whl", hash = "sha256:46be9c0685cce2ea02151aa8308f2c1b78581be41a5dd239448a941a210ef5dd"}, + {file = "rpds_py-0.13.0-cp312-none-win_amd64.whl", hash = "sha256:3c5b9ad4d3e05dfcf8629f0d534f92610e9805dbce2fcb9b3c801ddb886431d5"}, + {file = "rpds_py-0.13.0-cp38-cp38-macosx_10_7_x86_64.whl", hash = "sha256:66eb5aa36e857f768c598d2082fafb733eaf53e06e1169c6b4de65636e04ffd0"}, + {file = "rpds_py-0.13.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:c9f4c2b7d989426e9fe9b720211172cf10eb5f7aa16c63de2e5dc61457abcf35"}, + {file = "rpds_py-0.13.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c1e37dfffe8959a492b7b331995f291847a41a035b4aad82d6060f38e8378a2b"}, + {file = "rpds_py-0.13.0-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8220321f2dccd9d66f72639185247cb7bbdd90753bf0b6bfca0fa31dba8af23c"}, + {file = "rpds_py-0.13.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e8f1d466a9747213d3cf7e1afec849cc51edb70d5b4ae9a82eca0f172bfbb6d0"}, + {file = "rpds_py-0.13.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9c4c4b4ff3de834ec5c1c690e5a18233ca78547d003eb83664668ccf09ef1398"}, + {file = "rpds_py-0.13.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:525d19ef0a999229ef0f0a7687ab2c9a00d1b6a47a005006f4d8c4b8975fdcec"}, + {file = "rpds_py-0.13.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:0982b59d014efb84a57128e7e69399fb29ad8f2da5b0a5bcbfd12e211c00492e"}, + {file = "rpds_py-0.13.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:f714dd5b705f1c394d1b361d96486c4981055c434a7eafb1a3147ac75e34a3de"}, + {file = "rpds_py-0.13.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:766b573a964389ef0d91a26bb31e1b59dbc5d06eff7707f3dfcec23d93080ba3"}, + {file = "rpds_py-0.13.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:2ed65ad3fc5065d13e31e90794e0b52e405b63ae4fab1080caeaadc10a3439c5"}, + {file = "rpds_py-0.13.0-cp38-none-win32.whl", hash = "sha256:9645f7fe10a68b2396d238250b4b264c2632d2eb6ce2cb90aa0fe08adee194be"}, + {file = "rpds_py-0.13.0-cp38-none-win_amd64.whl", hash = "sha256:42d0ad129c102856a364ccc7d356faec017af86b3543a8539795f22b6cabad11"}, + {file = "rpds_py-0.13.0-cp39-cp39-macosx_10_7_x86_64.whl", hash = "sha256:95c11647fac2a3515ea2614a79e14b7c75025724ad54c91c7db4a6ea5c25ef19"}, + {file = "rpds_py-0.13.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:9435bf4832555c4f769c6be9401664357be33d5f5d8dc58f5c20fb8d21e2c45d"}, + {file = "rpds_py-0.13.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:54b1d671a74395344239ee3adbcd8c496525f6a2b2e54c40fec69620a31a8dcb"}, + {file = "rpds_py-0.13.0-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:13c8061115f1468de6ffdfb1d31b446e1bd814f1ff6e556862169aacb9fbbc5d"}, + {file = "rpds_py-0.13.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a78861123b002725633871a2096c3a4313224aab3d11b953dced87cfba702418"}, + {file = "rpds_py-0.13.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:97c1be5a018cdad54fa7e5f7d36b9ab45ef941a1d185987f18bdab0a42344012"}, + {file = "rpds_py-0.13.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e33b17915c8e4fb2ea8b91bb4c46cba92242c63dd38b87e869ead5ba217e2970"}, + {file = "rpds_py-0.13.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:153b6d8cf7ae4b9ffd09de6abeda661e351e3e06eaafd18a8c104ea00099b131"}, + {file = "rpds_py-0.13.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:da2852201e8e00c86be82c43d6893e6c380ef648ae53f337ffd1eaa35e3dfb8a"}, + {file = "rpds_py-0.13.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:a2383f400691fd7bd63347d4d75eb2fd525de9d901799a33a4e896c9885609f8"}, + {file = "rpds_py-0.13.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:d5bf560634ea6e9a59ceb2181a6cd6195a03f48cef9a400eb15e197e18f14548"}, + {file = "rpds_py-0.13.0-cp39-none-win32.whl", hash = "sha256:fdaef49055cc0c701fb17b9b34a38ef375e5cdb230b3722d4a12baf9b7cbc6d3"}, + {file = "rpds_py-0.13.0-cp39-none-win_amd64.whl", hash = "sha256:26660c74a20fe249fad75ca00bbfcf60e57c3fdbde92971c88a20e07fea1de64"}, + {file = "rpds_py-0.13.0-pp310-pypy310_pp73-macosx_10_7_x86_64.whl", hash = "sha256:28324f2f0247d407daabf7ff357ad9f36126075c92a0cf5319396d96ff4e1248"}, + {file = "rpds_py-0.13.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:b431c2c0ff1ea56048a2b066d99d0c2d151ae7625b20be159b7e699f3e80390b"}, + {file = "rpds_py-0.13.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7472bd60a8293217444bdc6a46e516feb8d168da44d5f3fccea0336e88e3b79a"}, + {file = "rpds_py-0.13.0-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:169063f346b8fd84f47d986c9c48e6094eb38b839c1287e7cb886b8a2b32195d"}, + {file = "rpds_py-0.13.0-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:eef7ee7c70f8b8698be468d54f9f5e01804f3a1dd5657e8a96363dbd52b9b5ec"}, + {file = "rpds_py-0.13.0-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:762013dd59df12380c5444f61ccbf9ae1297027cabbd7aa25891f724ebf8c8f7"}, + {file = "rpds_py-0.13.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:152570689a27ae0be1d5f50b21dad38d450b9227d0974f23bd400400ea087e88"}, + {file = "rpds_py-0.13.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d70a93a40e55da117c511ddc514642bc7d59a95a99137168a5f3f2f876b47962"}, + {file = "rpds_py-0.13.0-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:e6c6fed07d13b9e0fb689356c40c81f1aa92e3c9d91d8fd5816a0348ccd999f7"}, + {file = "rpds_py-0.13.0-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:cdded3cf9e36840b09ccef714d5fa74a03f4eb6cf81e694226ed9cb5e6f90de0"}, + {file = "rpds_py-0.13.0-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:e1f40faf406c52c7ae7d208b9140377c06397248978ccb03fbfbb30a0571e359"}, + {file = "rpds_py-0.13.0-pp38-pypy38_pp73-macosx_10_7_x86_64.whl", hash = "sha256:c10326e30c97a95b7e1d75e5200ef0b9827aa0f861e331e43b15dfdfd63e669b"}, + {file = "rpds_py-0.13.0-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:afde37e3763c602d0385bce5c12f262e7b1dd2a0f323e239fa9d7b2d4d5d8509"}, + {file = "rpds_py-0.13.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4084ab6840bd4d79eff3b5f497add847a7db31ce5a0c2d440c90b2d2b7011857"}, + {file = "rpds_py-0.13.0-pp38-pypy38_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:1c9c9cb48ab77ebfa47db25b753f594d4f44959cfe43b713439ca6e3c9329671"}, + {file = "rpds_py-0.13.0-pp38-pypy38_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:533d728ea5ad5253af3395102723ca8a77b62de47b2295155650c9a88fcdeec8"}, + {file = "rpds_py-0.13.0-pp38-pypy38_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1f22cab655b41033d430f20266bf563b35038a7f01c9a099b0ccfd30a7fb9247"}, + {file = "rpds_py-0.13.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b9a0507342c37132813449393e6e6f351bbff376031cfff1ee6e616402ac7908"}, + {file = "rpds_py-0.13.0-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4eb1faf8e2ee9a2de3cb3ae4c8c355914cdc85f2cd7f27edf76444c9550ce1e7"}, + {file = "rpds_py-0.13.0-pp38-pypy38_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:a61a152d61e3ae26e0bbba7b2f568f6f25ca0abdeb6553eca7e7c45b59d9b1a9"}, + {file = "rpds_py-0.13.0-pp38-pypy38_pp73-musllinux_1_2_i686.whl", hash = "sha256:e499bf2200eb74774a6f85a7465e3bc5273fa8ef0055590d97a88c1e7ea02eea"}, + {file = "rpds_py-0.13.0-pp38-pypy38_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:1e5becd0de924616ca9a12abeb6458568d1dc8fe5c670d5cdb738402a8a8429d"}, + {file = "rpds_py-0.13.0-pp39-pypy39_pp73-macosx_10_7_x86_64.whl", hash = "sha256:70cfe098d915f566eeebcb683f49f9404d2f948432891b6e075354336eda9dfb"}, + {file = "rpds_py-0.13.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:2e73511e88368f93c24efe7c9a20b319eaa828bc7431f8a17713efb9e31a39fa"}, + {file = "rpds_py-0.13.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c07cb9bcccd08f9bc2fd05bf586479df4272ea5a6a70fbcb59b018ed48a5a84d"}, + {file = "rpds_py-0.13.0-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8c4e84016ba225e09df20fed8befe8c68d14fbeff6078f4a0ff907ae2095e17e"}, + {file = "rpds_py-0.13.0-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6ad465e5a70580ca9c1944f43a9a71bca3a7b74554347fc96ca0479eca8981f9"}, + {file = "rpds_py-0.13.0-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:189aebd44a07fa7b7966cf78b85bde8335b0b6c3b1c4ef5589f8c03176830107"}, + {file = "rpds_py-0.13.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9f50ca0460f1f7a89ab9b8355d83ac993d5998ad4218e76654ecf8afe648d8aa"}, + {file = "rpds_py-0.13.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f6c225011467021879c0482316e42d8a28852fc29f0c15d2a435ff457cadccd4"}, + {file = "rpds_py-0.13.0-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:1e63b32b856c0f08a56b76967d61b6ad811d8d330a8aebb9d21afadd82a296f6"}, + {file = "rpds_py-0.13.0-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:7e5fbe9800f09c56967fda88c4d9272955e781699a66102bd098f22511a3f260"}, + {file = "rpds_py-0.13.0-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:fea99967d4a978ce95dd52310bcb4a943b77c61725393bca631b0908047d6e2f"}, + {file = "rpds_py-0.13.0.tar.gz", hash = "sha256:35cc91cbb0b775705e0feb3362490b8418c408e9e3c3b9cb3b02f6e495f03ee7"}, ] [[package]] @@ -3514,4 +3497,4 @@ virustotal = ["validators"] [metadata] lock-version = "2.0" python-versions = "^3.8" -content-hash = "503b5b6e7bdfb1151e543cc487192595798f831e006317165c19aa1177e9356f" +content-hash = "70fc3f18938b373b0719fd1e6df0e54420a55bd4684d839904929a2136600e61" diff --git a/pyproject.toml b/pyproject.toml index a28bf24..ae561c9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -45,7 +45,7 @@ requests = "^2.31.0" python-dateutil = "^2.8.2" jsonschema = ">=4.17.3" deprecated = "^1.2.14" -extract_msg = {version = "^0.45.0", optional = true} +extract_msg = {version = "^0.46.2", optional = true} RTFDE = {version = "^0.1.0", optional = true} oletools = {version = "^0.60.1", optional = true} python-magic = {version = "^0.4.27", optional = true} From 2dcb5f1efaf10c281b84d0f0ca1ab2b37a880715 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Vinot?= Date: Fri, 17 Nov 2023 13:21:18 +0100 Subject: [PATCH 04/80] fix: Update calls to getStringStream to the public method --- pymisp/tools/emailobject.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pymisp/tools/emailobject.py b/pymisp/tools/emailobject.py index 8093872..cb75941 100644 --- a/pymisp/tools/emailobject.py +++ b/pymisp/tools/emailobject.py @@ -173,7 +173,7 @@ class EMailObject(AbstractMISPObjectGenerator): _html = body.get('html', {}).get('obj') for attch in attachments: if _html.find("cid:{0}".format(attch.cid)) != -1: - _content_type = attch._getStringStream('__substg1.0_370E') + _content_type = attch.getStringStream('__substg1.0_370E') maintype, subtype = _content_type.split("/", 1) related_content[attch.cid] = (attch, {'obj': attch.data, @@ -210,7 +210,7 @@ class EMailObject(AbstractMISPObjectGenerator): message.add_alternative(**mime_dict) for attch in attachments: # Add attachments at the end. if attch.cid not in related_content.keys(): - _content_type = attch._getStringStream('__substg1.0_370E') + _content_type = attch.getStringStream('__substg1.0_370E') maintype, subtype = _content_type.split("/", 1) message.add_attachment(attch.data, maintype=maintype, From 199532113aeea07629b60ea31558d138c659c04e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Vinot?= Date: Fri, 17 Nov 2023 13:57:02 +0100 Subject: [PATCH 05/80] fix: eml and msg are in sync again. --- tests/test_emailobject.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/tests/test_emailobject.py b/tests/test_emailobject.py index 1940f5f..64f57c8 100644 --- a/tests/test_emailobject.py +++ b/tests/test_emailobject.py @@ -64,16 +64,13 @@ class TestEmailObject(unittest.TestCase): self._get_values(eml_email_object, "to")[0]) self.assertEqual(self._get_values(email_object, "from")[0], self._get_values(eml_email_object, "from")[0]) - dirty_display_name = self._get_values(email_object, "from-display-name")[0] - dirty_display_name = dirty_display_name[:-2] + dirty_display_name[-1] - self.assertEqual(dirty_display_name, + self.assertEqual(self._get_values(email_object, "from-display-name")[0], self._get_values(eml_email_object, "from-display-name")[0]) self.assertEqual(len(self._get_values(email_object, "email-body")), 2) self.assertEqual(self._get_values(email_object, "received-header-ip"), self._get_values(eml_email_object, "received-header-ip")) - def test_bom_encoded(self): """Test utf-8-sig encoded email""" bom_email_object = EMailObject(Path("tests/email_testfiles/mail_1_bom.eml")) From cc6391233c01362a1b4b483c4ea8e67f306e3459 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Vinot?= Date: Thu, 23 Nov 2023 13:44:13 +0100 Subject: [PATCH 06/80] chg: Bump version, changelog --- CHANGELOG.txt | 20 +++ poetry.lock | 287 ++++++++++++++++++++------------------- pymisp/data/misp-objects | 2 +- pyproject.toml | 6 +- 4 files changed, 168 insertions(+), 147 deletions(-) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index bb9f035..a9015d4 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -2,6 +2,25 @@ Changelog ========= +v2.4.179 (2023-11-23) +--------------------- + +Changes +~~~~~~~ +- Bump deps. [Raphaël Vinot] +- Bump deps. [Raphaël Vinot] +- [misp-objects] Bumped latest version. [Christian Studer] + +Fix +~~~ +- Eml and msg are in sync again. [Raphaël Vinot] +- Update calls to getStringStream to the public method. [Raphaël Vinot] +- Avoid confusing error when an auth key is limited to an IP. [Raphaël + Vinot] + + Fix #1099 + + v2.4.178 (2023-10-24) --------------------- @@ -11,6 +30,7 @@ New Changes ~~~~~~~ +- Bump changelog. [Raphaël Vinot] - Bump version, make __version__ dynamic. [Raphaël Vinot] - Bump deps, allow older jsonschema for compatibility. [Raphaël Vinot] - Bump deps. [Raphaël Vinot] diff --git a/poetry.lock b/poetry.lock index 015e598..6f34fc5 100644 --- a/poetry.lock +++ b/poetry.lock @@ -13,13 +13,13 @@ files = [ [[package]] name = "anyio" -version = "4.0.0" +version = "4.1.0" description = "High level compatibility layer for multiple asynchronous event loop implementations" optional = false python-versions = ">=3.8" files = [ - {file = "anyio-4.0.0-py3-none-any.whl", hash = "sha256:cfdb2b588b9fc25ede96d8db56ed50848b0b649dca3dd1df0b11f683bb9e0b5f"}, - {file = "anyio-4.0.0.tar.gz", hash = "sha256:f7ed51751b2c2add651e5747c891b47e26d2a21be5d32d9311dfe9692f3e5d7a"}, + {file = "anyio-4.1.0-py3-none-any.whl", hash = "sha256:56a415fbc462291813a94528a779597226619c8e78af7de0507333f700011e5f"}, + {file = "anyio-4.1.0.tar.gz", hash = "sha256:5a0bec7085176715be77df87fc66d6c9d70626bd752fcc85f57cdbee5b3760da"}, ] [package.dependencies] @@ -28,9 +28,9 @@ idna = ">=2.8" sniffio = ">=1.1" [package.extras] -doc = ["Sphinx (>=7)", "packaging", "sphinx-autodoc-typehints (>=1.2.0)"] -test = ["anyio[trio]", "coverage[toml] (>=7)", "hypothesis (>=4.0)", "psutil (>=5.9)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "uvloop (>=0.17)"] -trio = ["trio (>=0.22)"] +doc = ["Sphinx (>=7)", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx-rtd-theme"] +test = ["anyio[trio]", "coverage[toml] (>=7)", "exceptiongroup (>=1.2.0)", "hypothesis (>=4.0)", "psutil (>=5.9)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "uvloop (>=0.17)"] +trio = ["trio (>=0.23)"] [[package]] name = "appnope" @@ -395,13 +395,13 @@ cffi = ">=1.0.0" [[package]] name = "certifi" -version = "2023.7.22" +version = "2023.11.17" description = "Python package for providing Mozilla's CA Bundle." optional = false python-versions = ">=3.6" files = [ - {file = "certifi-2023.7.22-py3-none-any.whl", hash = "sha256:92d6037539857d8206b8f6ae472e8b77db8058fec5937a1ef3f54304089edbb9"}, - {file = "certifi-2023.7.22.tar.gz", hash = "sha256:539cc1d13202e33ca466e88b2807e29f4c13049d6d87031a3c110744495cb082"}, + {file = "certifi-2023.11.17-py3-none-any.whl", hash = "sha256:e036ab49d5b79556f99cfc2d9320b34cfbe5be05c5871b51de9329f0603b0474"}, + {file = "certifi-2023.11.17.tar.gz", hash = "sha256:9b469f3a900bf28dc19b8cfbf8019bf47f7fdd1a65a1d4ffb98fc14166beb4d1"}, ] [[package]] @@ -842,13 +842,13 @@ files = [ [[package]] name = "exceptiongroup" -version = "1.1.3" +version = "1.2.0" description = "Backport of PEP 654 (exception groups)" optional = false python-versions = ">=3.7" files = [ - {file = "exceptiongroup-1.1.3-py3-none-any.whl", hash = "sha256:343280667a4585d195ca1cf9cef84a4e178c4b6cf2274caef9859782b567d5e3"}, - {file = "exceptiongroup-1.1.3.tar.gz", hash = "sha256:097acd85d473d75af5bb98e41b61ff7fe35efe6675e4f9370ec6ec5126d160e9"}, + {file = "exceptiongroup-1.2.0-py3-none-any.whl", hash = "sha256:4bfd3996ac73b41e9b9628b04e079f193850720ea5945fc96a08633c66912f14"}, + {file = "exceptiongroup-1.2.0.tar.gz", hash = "sha256:91f5c769735f051a4290d52edd0858999b57e5876e9f85937691bd4c9fa3ed68"}, ] [package.extras] @@ -992,13 +992,13 @@ files = [ [[package]] name = "ipykernel" -version = "6.26.0" +version = "6.27.0" description = "IPython Kernel for Jupyter" optional = false python-versions = ">=3.8" files = [ - {file = "ipykernel-6.26.0-py3-none-any.whl", hash = "sha256:3ba3dc97424b87b31bb46586b5167b3161b32d7820b9201a9e698c71e271602c"}, - {file = "ipykernel-6.26.0.tar.gz", hash = "sha256:553856658eb8430bbe9653ea041a41bff63e9606fc4628873fc92a6cf3abd404"}, + {file = "ipykernel-6.27.0-py3-none-any.whl", hash = "sha256:4388caa3c2cba0a381e20d289545e88a8aef1fe57a884d4c018718ec8c23c121"}, + {file = "ipykernel-6.27.0.tar.gz", hash = "sha256:7f4986f606581be73bfb32dc7a1ac9fa0e804c9be50ddf1c7a119413e982693f"}, ] [package.dependencies] @@ -1360,13 +1360,13 @@ test = ["coverage", "jupyter-server (>=2.0.0)", "pytest (>=7.0)", "pytest-cov", [[package]] name = "jupyterlab" -version = "4.0.8" +version = "4.0.9" description = "JupyterLab computational environment" optional = false python-versions = ">=3.8" files = [ - {file = "jupyterlab-4.0.8-py3-none-any.whl", hash = "sha256:2ff5aa2a51eb21df241d6011c236e88bd1ff9a5dbb75bebc54472f9c18bfffa4"}, - {file = "jupyterlab-4.0.8.tar.gz", hash = "sha256:c4fe93f977bcc987bd395d7fae5ab02e0c042bf4e0f7c95196f3e2e578c2fb3a"}, + {file = "jupyterlab-4.0.9-py3-none-any.whl", hash = "sha256:9f6f8e36d543fdbcc3df961a1d6a3f524b4a4001be0327a398f68fa4e534107c"}, + {file = "jupyterlab-4.0.9.tar.gz", hash = "sha256:9ebada41d52651f623c0c9f069ddb8a21d6848e4c887d8e5ddc0613166ed5c0b"}, ] [package.dependencies] @@ -1386,31 +1386,31 @@ tornado = ">=6.2.0" traitlets = "*" [package.extras] -dev = ["black[jupyter] (==23.10.1)", "build", "bump2version", "coverage", "hatch", "pre-commit", "pytest-cov", "ruff (==0.0.292)"] +dev = ["black[jupyter] (==23.10.1)", "build", "bump2version", "coverage", "hatch", "pre-commit", "pytest-cov", "ruff (==0.1.4)"] docs = ["jsx-lexer", "myst-parser", "pydata-sphinx-theme (>=0.13.0)", "pytest", "pytest-check-links", "pytest-tornasync", "sphinx (>=1.8,<7.2.0)", "sphinx-copybutton"] docs-screenshots = ["altair (==5.0.1)", "ipython (==8.14.0)", "ipywidgets (==8.0.6)", "jupyterlab-geojson (==3.4.0)", "jupyterlab-language-pack-zh-cn (==4.0.post0)", "matplotlib (==3.7.1)", "nbconvert (>=7.0.0)", "pandas (==2.0.2)", "scipy (==1.10.1)", "vega-datasets (==0.9.0)"] test = ["coverage", "pytest (>=7.0)", "pytest-check-links (>=0.7)", "pytest-console-scripts", "pytest-cov", "pytest-jupyter (>=0.5.3)", "pytest-timeout", "pytest-tornasync", "requests", "requests-cache", "virtualenv"] [[package]] name = "jupyterlab-pygments" -version = "0.2.2" +version = "0.3.0" description = "Pygments theme using JupyterLab CSS variables" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "jupyterlab_pygments-0.2.2-py2.py3-none-any.whl", hash = "sha256:2405800db07c9f770863bcf8049a529c3dd4d3e28536638bd7c1c01d2748309f"}, - {file = "jupyterlab_pygments-0.2.2.tar.gz", hash = "sha256:7405d7fde60819d905a9fa8ce89e4cd830e318cdad22a0030f7a901da705585d"}, + {file = "jupyterlab_pygments-0.3.0-py3-none-any.whl", hash = "sha256:841a89020971da1d8693f1a99997aefc5dc424bb1b251fd6322462a1b8842780"}, + {file = "jupyterlab_pygments-0.3.0.tar.gz", hash = "sha256:721aca4d9029252b11cfa9d185e5b5af4d54772bb8072f9b7036f4170054d35d"}, ] [[package]] name = "jupyterlab-server" -version = "2.25.1" +version = "2.25.2" description = "A set of server components for JupyterLab and JupyterLab like applications." optional = false python-versions = ">=3.8" files = [ - {file = "jupyterlab_server-2.25.1-py3-none-any.whl", hash = "sha256:dce9714d91fb3e53d2b37d0e0619fa26ed223c8e7b8c81cca112926de19b53a4"}, - {file = "jupyterlab_server-2.25.1.tar.gz", hash = "sha256:6491283b0000698eae1a38c48507930560dfcf7461aea0015368698aab34dd9c"}, + {file = "jupyterlab_server-2.25.2-py3-none-any.whl", hash = "sha256:5b1798c9cc6a44f65c757de9f97fc06fc3d42535afbf47d2ace5e964ab447aaf"}, + {file = "jupyterlab_server-2.25.2.tar.gz", hash = "sha256:bd0ec7a99ebcedc8bcff939ef86e52c378e44c2707e053fcd81d046ce979ee63"}, ] [package.dependencies] @@ -1972,13 +1972,13 @@ testing = ["pytest", "pytest-benchmark"] [[package]] name = "prometheus-client" -version = "0.18.0" +version = "0.19.0" description = "Python client for the Prometheus monitoring system." optional = false python-versions = ">=3.8" files = [ - {file = "prometheus_client-0.18.0-py3-none-any.whl", hash = "sha256:8de3ae2755f890826f4b6479e5571d4f74ac17a81345fe69a6778fdb92579184"}, - {file = "prometheus_client-0.18.0.tar.gz", hash = "sha256:35f7a8c22139e2bb7ca5a698e92d38145bc8dc74c1c0bf56f25cca886a764e17"}, + {file = "prometheus_client-0.19.0-py3-none-any.whl", hash = "sha256:c88b1e6ecf6b41cd8fb5731c7ae919bf66df6ec6fafa555cd6c0e16ca169ae92"}, + {file = "prometheus_client-0.19.0.tar.gz", hash = "sha256:4585b0d1223148c27a225b10dbec5ae9bc4c81a99a3fa80774fa6209935324e1"}, ] [package.extras] @@ -2039,13 +2039,13 @@ files = [ [[package]] name = "publicsuffixlist" -version = "0.10.0.20231109" +version = "0.10.0.20231122" description = "publicsuffixlist implement" optional = true python-versions = ">=2.6" files = [ - {file = "publicsuffixlist-0.10.0.20231109-py2.py3-none-any.whl", hash = "sha256:72888d1a5da95b78345bc8b228125c1e32896109efda1947d8df92a62cc325cd"}, - {file = "publicsuffixlist-0.10.0.20231109.tar.gz", hash = "sha256:72bdab12819527c05e5cb7f23eae00bb1bbb3843a55672b19523144449a38b61"}, + {file = "publicsuffixlist-0.10.0.20231122-py2.py3-none-any.whl", hash = "sha256:ce47acf7fb7e817fba8397b43896fcb4b4307d41e2c9d2f63418b3e65c7f15cb"}, + {file = "publicsuffixlist-0.10.0.20231122.tar.gz", hash = "sha256:d02ac754fa104d2dc8f593ef7ffe305905f8bd89f9bc079653135a9e39db17ad"}, ] [package.extras] @@ -2112,17 +2112,18 @@ files = [ [[package]] name = "pygments" -version = "2.16.1" +version = "2.17.2" description = "Pygments is a syntax highlighting package written in Python." optional = false python-versions = ">=3.7" files = [ - {file = "Pygments-2.16.1-py3-none-any.whl", hash = "sha256:13fc09fa63bc8d8671a6d247e1eb303c4b343eaee81d861f3404db2935653692"}, - {file = "Pygments-2.16.1.tar.gz", hash = "sha256:1daff0494820c69bc8941e407aa20f577374ee88364ee10a98fdbe0aece96e29"}, + {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 = "pyparsing" @@ -2541,110 +2542,110 @@ files = [ [[package]] name = "rpds-py" -version = "0.13.0" +version = "0.13.1" description = "Python bindings to Rust's persistent data structures (rpds)" optional = false python-versions = ">=3.8" files = [ - {file = "rpds_py-0.13.0-cp310-cp310-macosx_10_7_x86_64.whl", hash = "sha256:1758197cc8d7ff383c07405f188253535b4aa7fa745cbc54d221ae84b18e0702"}, - {file = "rpds_py-0.13.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:715df74cbcef4387d623c917f295352127f4b3e0388038d68fa577b4e4c6e540"}, - {file = "rpds_py-0.13.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c8a9cec0f49df9bac252d92f138c0d7708d98828e21fd57db78087d8f50b5656"}, - {file = "rpds_py-0.13.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5c2545bba02f68abdf398ef4990dc77592cc1e5d29438b35b3a3ca34d171fb4b"}, - {file = "rpds_py-0.13.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:95375c44ffb9ea2bc25d67fb66e726ea266ff1572df50b9556fe28a5f3519cd7"}, - {file = "rpds_py-0.13.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:54e513df45a8a9419e7952ffd26ac9a5b7b1df97fe72530421794b0de29f9d72"}, - {file = "rpds_py-0.13.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a25f514a53927b6b4bd04a9a6a13b55209df54f548660eeed673336c0c946d14"}, - {file = "rpds_py-0.13.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c1a920fa679ec2758411d66bf68840b0a21317b9954ab0e973742d723bb67709"}, - {file = "rpds_py-0.13.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:f9339d1404b87e6d8cb35e485945753be57a99ab9bb389f42629215b2f6bda0f"}, - {file = "rpds_py-0.13.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:c99f9dda2c959f7bb69a7125e192c74fcafb7a534a95ccf49313ae3a04807804"}, - {file = "rpds_py-0.13.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:bad6758df5f1042b35683bd1811d5432ac1b17700a5a2a51fdc293f7df5f7827"}, - {file = "rpds_py-0.13.0-cp310-none-win32.whl", hash = "sha256:2a29ec68fa9655ce9501bc6ae074b166e8b45c2dfcd2d71d90d1a61758ed8c73"}, - {file = "rpds_py-0.13.0-cp310-none-win_amd64.whl", hash = "sha256:244be953f13f148b0071d67a610f89cd72eb5013a147e517d6ca3f3f3b7e0380"}, - {file = "rpds_py-0.13.0-cp311-cp311-macosx_10_7_x86_64.whl", hash = "sha256:240279ca0b2afd6d4710afce1c94bf9e75fc161290bf62c0feba64d64780d80b"}, - {file = "rpds_py-0.13.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:25c9727da2dabc93664a18eda7a70feedf478f0c4c8294e4cdba7f60a479a246"}, - {file = "rpds_py-0.13.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:981e46e1e5064f95460381bff4353783b4b5ce351c930e5b507ebe0278c61dac"}, - {file = "rpds_py-0.13.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6052bb47ea583646b8ff562acacb9a2ec5ec847267049cbae3919671929e94c6"}, - {file = "rpds_py-0.13.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:87f591ff8cc834fa01ca5899ab5edcd7ee590492a9cdcf43424ac142e731ce3e"}, - {file = "rpds_py-0.13.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:62772259b3381e2aabf274c74fd1e1ac03b0524de0a6593900684becfa8cfe4b"}, - {file = "rpds_py-0.13.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b4de9d20fe68c16b4d97f551a09920745add0c86430262230528b83c2ed2fe90"}, - {file = "rpds_py-0.13.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b70a54fb628c1d6400e351674a31ba63d2912b8c5b707f99b408674a5d8b69ab"}, - {file = "rpds_py-0.13.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:2063ab9cd1be7ef6b5ed0f408e2bdf32c060b6f40c097a468f32864731302636"}, - {file = "rpds_py-0.13.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:84f7f3f18d29a1c645729634003d21d84028bd9c2fd78eba9d028998f46fa5aa"}, - {file = "rpds_py-0.13.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f7c7ddc8d1a64623068da5a15e28001fbd0f0aff754aae7a75a4be5042191638"}, - {file = "rpds_py-0.13.0-cp311-none-win32.whl", hash = "sha256:8a33d2b6340261191bb59adb5a453fa6c7d99de85552bd4e8196411f0509c9bf"}, - {file = "rpds_py-0.13.0-cp311-none-win_amd64.whl", hash = "sha256:8b9c1dd90461940315981499df62a627571c4f0992e8bafc5396d33916224cac"}, - {file = "rpds_py-0.13.0-cp312-cp312-macosx_10_7_x86_64.whl", hash = "sha256:15a2d542de5cbfc6abddc4846d9412b59f8ee9c8dfa0b9c92a29321297c91745"}, - {file = "rpds_py-0.13.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8dd69e01b29ff45a0062cad5c480d8aa9301c3ef09da471f86337a78eb2d3405"}, - {file = "rpds_py-0.13.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:efdd02971a02f98492a72b25484f1f6125fb9f2166e48cc4c9bfa563349c851b"}, - {file = "rpds_py-0.13.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:91ca9aaee7ccdfa66d800b5c4ec634fefca947721bab52d6ad2f6350969a3771"}, - {file = "rpds_py-0.13.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:afcec1f5b09d0db70aeb2d90528a9164acb61841a3124e28f6ac0137f4c36cb4"}, - {file = "rpds_py-0.13.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5c6824673f66c47f7ee759c21e973bfce3ceaf2c25cb940cb45b41105dc914e8"}, - {file = "rpds_py-0.13.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:50b6d80925dfeb573fc5e38582fb9517c6912dc462cc858a11c8177b0837127a"}, - {file = "rpds_py-0.13.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:3a1a38512925829784b5dc38591c757b80cfce115c72c594dc59567dab62b9c4"}, - {file = "rpds_py-0.13.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:977c6123c359dcc70ce3161b781ab70b0d342de2666944b776617e01a0a7822a"}, - {file = "rpds_py-0.13.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:c472409037e05ed87b99430f97a6b82130328bb977502813547e8ee6a3392502"}, - {file = "rpds_py-0.13.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:28bb22019f4a783ea06a6b81437d5996551869e8a722ee8720b744f7684d97f4"}, - {file = "rpds_py-0.13.0-cp312-none-win32.whl", hash = "sha256:46be9c0685cce2ea02151aa8308f2c1b78581be41a5dd239448a941a210ef5dd"}, - {file = "rpds_py-0.13.0-cp312-none-win_amd64.whl", hash = "sha256:3c5b9ad4d3e05dfcf8629f0d534f92610e9805dbce2fcb9b3c801ddb886431d5"}, - {file = "rpds_py-0.13.0-cp38-cp38-macosx_10_7_x86_64.whl", hash = "sha256:66eb5aa36e857f768c598d2082fafb733eaf53e06e1169c6b4de65636e04ffd0"}, - {file = "rpds_py-0.13.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:c9f4c2b7d989426e9fe9b720211172cf10eb5f7aa16c63de2e5dc61457abcf35"}, - {file = "rpds_py-0.13.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c1e37dfffe8959a492b7b331995f291847a41a035b4aad82d6060f38e8378a2b"}, - {file = "rpds_py-0.13.0-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8220321f2dccd9d66f72639185247cb7bbdd90753bf0b6bfca0fa31dba8af23c"}, - {file = "rpds_py-0.13.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e8f1d466a9747213d3cf7e1afec849cc51edb70d5b4ae9a82eca0f172bfbb6d0"}, - {file = "rpds_py-0.13.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9c4c4b4ff3de834ec5c1c690e5a18233ca78547d003eb83664668ccf09ef1398"}, - {file = "rpds_py-0.13.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:525d19ef0a999229ef0f0a7687ab2c9a00d1b6a47a005006f4d8c4b8975fdcec"}, - {file = "rpds_py-0.13.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:0982b59d014efb84a57128e7e69399fb29ad8f2da5b0a5bcbfd12e211c00492e"}, - {file = "rpds_py-0.13.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:f714dd5b705f1c394d1b361d96486c4981055c434a7eafb1a3147ac75e34a3de"}, - {file = "rpds_py-0.13.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:766b573a964389ef0d91a26bb31e1b59dbc5d06eff7707f3dfcec23d93080ba3"}, - {file = "rpds_py-0.13.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:2ed65ad3fc5065d13e31e90794e0b52e405b63ae4fab1080caeaadc10a3439c5"}, - {file = "rpds_py-0.13.0-cp38-none-win32.whl", hash = "sha256:9645f7fe10a68b2396d238250b4b264c2632d2eb6ce2cb90aa0fe08adee194be"}, - {file = "rpds_py-0.13.0-cp38-none-win_amd64.whl", hash = "sha256:42d0ad129c102856a364ccc7d356faec017af86b3543a8539795f22b6cabad11"}, - {file = "rpds_py-0.13.0-cp39-cp39-macosx_10_7_x86_64.whl", hash = "sha256:95c11647fac2a3515ea2614a79e14b7c75025724ad54c91c7db4a6ea5c25ef19"}, - {file = "rpds_py-0.13.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:9435bf4832555c4f769c6be9401664357be33d5f5d8dc58f5c20fb8d21e2c45d"}, - {file = "rpds_py-0.13.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:54b1d671a74395344239ee3adbcd8c496525f6a2b2e54c40fec69620a31a8dcb"}, - {file = "rpds_py-0.13.0-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:13c8061115f1468de6ffdfb1d31b446e1bd814f1ff6e556862169aacb9fbbc5d"}, - {file = "rpds_py-0.13.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a78861123b002725633871a2096c3a4313224aab3d11b953dced87cfba702418"}, - {file = "rpds_py-0.13.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:97c1be5a018cdad54fa7e5f7d36b9ab45ef941a1d185987f18bdab0a42344012"}, - {file = "rpds_py-0.13.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e33b17915c8e4fb2ea8b91bb4c46cba92242c63dd38b87e869ead5ba217e2970"}, - {file = "rpds_py-0.13.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:153b6d8cf7ae4b9ffd09de6abeda661e351e3e06eaafd18a8c104ea00099b131"}, - {file = "rpds_py-0.13.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:da2852201e8e00c86be82c43d6893e6c380ef648ae53f337ffd1eaa35e3dfb8a"}, - {file = "rpds_py-0.13.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:a2383f400691fd7bd63347d4d75eb2fd525de9d901799a33a4e896c9885609f8"}, - {file = "rpds_py-0.13.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:d5bf560634ea6e9a59ceb2181a6cd6195a03f48cef9a400eb15e197e18f14548"}, - {file = "rpds_py-0.13.0-cp39-none-win32.whl", hash = "sha256:fdaef49055cc0c701fb17b9b34a38ef375e5cdb230b3722d4a12baf9b7cbc6d3"}, - {file = "rpds_py-0.13.0-cp39-none-win_amd64.whl", hash = "sha256:26660c74a20fe249fad75ca00bbfcf60e57c3fdbde92971c88a20e07fea1de64"}, - {file = "rpds_py-0.13.0-pp310-pypy310_pp73-macosx_10_7_x86_64.whl", hash = "sha256:28324f2f0247d407daabf7ff357ad9f36126075c92a0cf5319396d96ff4e1248"}, - {file = "rpds_py-0.13.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:b431c2c0ff1ea56048a2b066d99d0c2d151ae7625b20be159b7e699f3e80390b"}, - {file = "rpds_py-0.13.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7472bd60a8293217444bdc6a46e516feb8d168da44d5f3fccea0336e88e3b79a"}, - {file = "rpds_py-0.13.0-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:169063f346b8fd84f47d986c9c48e6094eb38b839c1287e7cb886b8a2b32195d"}, - {file = "rpds_py-0.13.0-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:eef7ee7c70f8b8698be468d54f9f5e01804f3a1dd5657e8a96363dbd52b9b5ec"}, - {file = "rpds_py-0.13.0-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:762013dd59df12380c5444f61ccbf9ae1297027cabbd7aa25891f724ebf8c8f7"}, - {file = "rpds_py-0.13.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:152570689a27ae0be1d5f50b21dad38d450b9227d0974f23bd400400ea087e88"}, - {file = "rpds_py-0.13.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d70a93a40e55da117c511ddc514642bc7d59a95a99137168a5f3f2f876b47962"}, - {file = "rpds_py-0.13.0-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:e6c6fed07d13b9e0fb689356c40c81f1aa92e3c9d91d8fd5816a0348ccd999f7"}, - {file = "rpds_py-0.13.0-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:cdded3cf9e36840b09ccef714d5fa74a03f4eb6cf81e694226ed9cb5e6f90de0"}, - {file = "rpds_py-0.13.0-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:e1f40faf406c52c7ae7d208b9140377c06397248978ccb03fbfbb30a0571e359"}, - {file = "rpds_py-0.13.0-pp38-pypy38_pp73-macosx_10_7_x86_64.whl", hash = "sha256:c10326e30c97a95b7e1d75e5200ef0b9827aa0f861e331e43b15dfdfd63e669b"}, - {file = "rpds_py-0.13.0-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:afde37e3763c602d0385bce5c12f262e7b1dd2a0f323e239fa9d7b2d4d5d8509"}, - {file = "rpds_py-0.13.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4084ab6840bd4d79eff3b5f497add847a7db31ce5a0c2d440c90b2d2b7011857"}, - {file = "rpds_py-0.13.0-pp38-pypy38_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:1c9c9cb48ab77ebfa47db25b753f594d4f44959cfe43b713439ca6e3c9329671"}, - {file = "rpds_py-0.13.0-pp38-pypy38_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:533d728ea5ad5253af3395102723ca8a77b62de47b2295155650c9a88fcdeec8"}, - {file = "rpds_py-0.13.0-pp38-pypy38_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1f22cab655b41033d430f20266bf563b35038a7f01c9a099b0ccfd30a7fb9247"}, - {file = "rpds_py-0.13.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b9a0507342c37132813449393e6e6f351bbff376031cfff1ee6e616402ac7908"}, - {file = "rpds_py-0.13.0-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4eb1faf8e2ee9a2de3cb3ae4c8c355914cdc85f2cd7f27edf76444c9550ce1e7"}, - {file = "rpds_py-0.13.0-pp38-pypy38_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:a61a152d61e3ae26e0bbba7b2f568f6f25ca0abdeb6553eca7e7c45b59d9b1a9"}, - {file = "rpds_py-0.13.0-pp38-pypy38_pp73-musllinux_1_2_i686.whl", hash = "sha256:e499bf2200eb74774a6f85a7465e3bc5273fa8ef0055590d97a88c1e7ea02eea"}, - {file = "rpds_py-0.13.0-pp38-pypy38_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:1e5becd0de924616ca9a12abeb6458568d1dc8fe5c670d5cdb738402a8a8429d"}, - {file = "rpds_py-0.13.0-pp39-pypy39_pp73-macosx_10_7_x86_64.whl", hash = "sha256:70cfe098d915f566eeebcb683f49f9404d2f948432891b6e075354336eda9dfb"}, - {file = "rpds_py-0.13.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:2e73511e88368f93c24efe7c9a20b319eaa828bc7431f8a17713efb9e31a39fa"}, - {file = "rpds_py-0.13.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c07cb9bcccd08f9bc2fd05bf586479df4272ea5a6a70fbcb59b018ed48a5a84d"}, - {file = "rpds_py-0.13.0-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8c4e84016ba225e09df20fed8befe8c68d14fbeff6078f4a0ff907ae2095e17e"}, - {file = "rpds_py-0.13.0-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6ad465e5a70580ca9c1944f43a9a71bca3a7b74554347fc96ca0479eca8981f9"}, - {file = "rpds_py-0.13.0-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:189aebd44a07fa7b7966cf78b85bde8335b0b6c3b1c4ef5589f8c03176830107"}, - {file = "rpds_py-0.13.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9f50ca0460f1f7a89ab9b8355d83ac993d5998ad4218e76654ecf8afe648d8aa"}, - {file = "rpds_py-0.13.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f6c225011467021879c0482316e42d8a28852fc29f0c15d2a435ff457cadccd4"}, - {file = "rpds_py-0.13.0-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:1e63b32b856c0f08a56b76967d61b6ad811d8d330a8aebb9d21afadd82a296f6"}, - {file = "rpds_py-0.13.0-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:7e5fbe9800f09c56967fda88c4d9272955e781699a66102bd098f22511a3f260"}, - {file = "rpds_py-0.13.0-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:fea99967d4a978ce95dd52310bcb4a943b77c61725393bca631b0908047d6e2f"}, - {file = "rpds_py-0.13.0.tar.gz", hash = "sha256:35cc91cbb0b775705e0feb3362490b8418c408e9e3c3b9cb3b02f6e495f03ee7"}, + {file = "rpds_py-0.13.1-cp310-cp310-macosx_10_7_x86_64.whl", hash = "sha256:83feb0f682d75a09ddc11aa37ba5c07dd9b824b22915207f6176ea458474ff75"}, + {file = "rpds_py-0.13.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fa84bbe22ffa108f91631935c28a623001e335d66e393438258501e618fb0dde"}, + {file = "rpds_py-0.13.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e04f8c76b8d5c70695b4e8f1d0b391d8ef91df00ef488c6c1ffb910176459bc6"}, + {file = "rpds_py-0.13.1-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:032c242a595629aacace44128f9795110513ad27217b091e834edec2fb09e800"}, + {file = "rpds_py-0.13.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:91276caef95556faeb4b8f09fe4439670d3d6206fee78d47ddb6e6de837f0b4d"}, + {file = "rpds_py-0.13.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d22f2cb82e0b40e427a74a93c9a4231335bbc548aed79955dde0b64ea7f88146"}, + {file = "rpds_py-0.13.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:63c9e2794329ef070844ff9bfc012004aeddc0468dc26970953709723f76c8a5"}, + {file = "rpds_py-0.13.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c797ea56f36c6f248656f0223b11307fdf4a1886f3555eba371f34152b07677f"}, + {file = "rpds_py-0.13.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:82dbcd6463e580bcfb7561cece35046aaabeac5a9ddb775020160b14e6c58a5d"}, + {file = "rpds_py-0.13.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:736817dbbbd030a69a1faf5413a319976c9c8ba8cdcfa98c022d3b6b2e01eca6"}, + {file = "rpds_py-0.13.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:1f36a1e80ef4ed1996445698fd91e0d3e54738bf597c9995118b92da537d7a28"}, + {file = "rpds_py-0.13.1-cp310-none-win32.whl", hash = "sha256:4f13d3f6585bd07657a603780e99beda96a36c86acaba841f131e81393958336"}, + {file = "rpds_py-0.13.1-cp310-none-win_amd64.whl", hash = "sha256:545e94c84575057d3d5c62634611858dac859702b1519b6ffc58eca7fb1adfcf"}, + {file = "rpds_py-0.13.1-cp311-cp311-macosx_10_7_x86_64.whl", hash = "sha256:6bfe72b249264cc1ff2f3629be240d7d2fdc778d9d298087cdec8524c91cd11f"}, + {file = "rpds_py-0.13.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:edc91c50e17f5cd945d821f0f1af830522dba0c10267c3aab186dc3dbaab8def"}, + {file = "rpds_py-0.13.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2eca04a365be380ca1f8fa48b334462e19e3382c0bb7386444d8ca43aa01c481"}, + {file = "rpds_py-0.13.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3e3ac5b602fea378243f993d8b707189f9061e55ebb4e56cb9fdef8166060f28"}, + {file = "rpds_py-0.13.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dfb5d2ab183c0efe5e7b8917e4eaa2e837aacafad8a69b89aa6bc81550eed857"}, + {file = "rpds_py-0.13.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d9793d46d3e6522ae58e9321032827c9c0df1e56cbe5d3de965facb311aed6aa"}, + {file = "rpds_py-0.13.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9cd935c0220d012a27c20135c140f9cdcbc6249d5954345c81bfb714071b985c"}, + {file = "rpds_py-0.13.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:37b08df45f02ff1866043b95096cbe91ac99de05936dd09d6611987a82a3306a"}, + {file = "rpds_py-0.13.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:ad666a904212aa9a6c77da7dce9d5170008cda76b7776e6731928b3f8a0d40fa"}, + {file = "rpds_py-0.13.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:8a6ad8429340e0a4de89353447c6441329def3632e7b2293a7d6e873217d3c2b"}, + {file = "rpds_py-0.13.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:7c40851b659d958c5245c1236e34f0d065cc53dca8d978b49a032c8e0adfda6e"}, + {file = "rpds_py-0.13.1-cp311-none-win32.whl", hash = "sha256:4145172ab59b6c27695db6d78d040795f635cba732cead19c78cede74800949a"}, + {file = "rpds_py-0.13.1-cp311-none-win_amd64.whl", hash = "sha256:46a07a258bda12270de02b34c4884f200f864bba3dcd6e3a37fef36a168b859d"}, + {file = "rpds_py-0.13.1-cp312-cp312-macosx_10_7_x86_64.whl", hash = "sha256:ba4432301ad7eeb1b00848cf46fae0e5fecfd18a8cb5fdcf856c67985f79ecc7"}, + {file = "rpds_py-0.13.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d22e0660de24bd8e9ac82f4230a22a5fe4e397265709289d61d5fb333839ba50"}, + {file = "rpds_py-0.13.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76a8374b294e4ccb39ccaf11d39a0537ed107534139c00b4393ca3b542cc66e5"}, + {file = "rpds_py-0.13.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7d152ec7bb431040af2500e01436c9aa0d993f243346f0594a15755016bf0be1"}, + {file = "rpds_py-0.13.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:74a2044b870df7c9360bb3ce7e12f9ddf8e72e49cd3a353a1528cbf166ad2383"}, + {file = "rpds_py-0.13.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:960e7e460fda2d0af18c75585bbe0c99f90b8f09963844618a621b804f8c3abe"}, + {file = "rpds_py-0.13.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:37f79f4f1f06cc96151f4a187528c3fd4a7e1065538a4af9eb68c642365957f7"}, + {file = "rpds_py-0.13.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:cd4ea56c9542ad0091dfdef3e8572ae7a746e1e91eb56c9e08b8d0808b40f1d1"}, + {file = "rpds_py-0.13.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:0290712eb5603a725769b5d857f7cf15cf6ca93dda3128065bbafe6fdb709beb"}, + {file = "rpds_py-0.13.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:0b70c1f800059c92479dc94dda41288fd6607f741f9b1b8f89a21a86428f6383"}, + {file = "rpds_py-0.13.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:3dd5fb7737224e1497c886fb3ca681c15d9c00c76171f53b3c3cc8d16ccfa7fb"}, + {file = "rpds_py-0.13.1-cp312-none-win32.whl", hash = "sha256:74be3b215a5695690a0f1a9f68b1d1c93f8caad52e23242fcb8ba56aaf060281"}, + {file = "rpds_py-0.13.1-cp312-none-win_amd64.whl", hash = "sha256:f47eef55297799956464efc00c74ae55c48a7b68236856d56183fe1ddf866205"}, + {file = "rpds_py-0.13.1-cp38-cp38-macosx_10_7_x86_64.whl", hash = "sha256:e4a45ba34f904062c63049a760790c6a2fa7a4cc4bd160d8af243b12371aaa05"}, + {file = "rpds_py-0.13.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:20147996376be452cd82cd6c17701daba69a849dc143270fa10fe067bb34562a"}, + {file = "rpds_py-0.13.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42b9535aa22ab023704cfc6533e968f7e420affe802d85e956d8a7b4c0b0b5ea"}, + {file = "rpds_py-0.13.1-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d4fa1eeb9bea6d9b64ac91ec51ee94cc4fc744955df5be393e1c923c920db2b0"}, + {file = "rpds_py-0.13.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2b2415d5a7b7ee96aa3a54d4775c1fec140476a17ee12353806297e900eaeddc"}, + {file = "rpds_py-0.13.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:577d40a72550eac1386b77b43836151cb61ff6700adacda2ad4d883ca5a0b6f2"}, + {file = "rpds_py-0.13.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:af2d1648eb625a460eee07d3e1ea3a4a6e84a1fb3a107f6a8e95ac19f7dcce67"}, + {file = "rpds_py-0.13.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5b769396eb358d6b55dbf78f3f7ca631ca1b2fe02136faad5af74f0111b4b6b7"}, + {file = "rpds_py-0.13.1-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:249c8e0055ca597707d71c5ad85fd2a1c8fdb99386a8c6c257e1b47b67a9bec1"}, + {file = "rpds_py-0.13.1-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:fe30ef31172bdcf946502a945faad110e8fff88c32c4bec9a593df0280e64d8a"}, + {file = "rpds_py-0.13.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:2647192facf63be9ed2d7a49ceb07efe01dc6cfb083bd2cc53c418437400cb99"}, + {file = "rpds_py-0.13.1-cp38-none-win32.whl", hash = "sha256:4011d5c854aa804c833331d38a2b6f6f2fe58a90c9f615afdb7aa7cf9d31f721"}, + {file = "rpds_py-0.13.1-cp38-none-win_amd64.whl", hash = "sha256:7cfae77da92a20f56cf89739a557b76e5c6edc094f6ad5c090b9e15fbbfcd1a4"}, + {file = "rpds_py-0.13.1-cp39-cp39-macosx_10_7_x86_64.whl", hash = "sha256:e9be1f7c5f9673616f875299339984da9447a40e3aea927750c843d6e5e2e029"}, + {file = "rpds_py-0.13.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:839676475ac2ccd1532d36af3d10d290a2ca149b702ed464131e450a767550df"}, + {file = "rpds_py-0.13.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a90031658805c63fe488f8e9e7a88b260ea121ba3ee9cdabcece9c9ddb50da39"}, + {file = "rpds_py-0.13.1-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8ba9fbc5d6e36bfeb5292530321cc56c4ef3f98048647fabd8f57543c34174ec"}, + {file = "rpds_py-0.13.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:08832078767545c5ee12561ce980714e1e4c6619b5b1e9a10248de60cddfa1fd"}, + {file = "rpds_py-0.13.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:19f5aa7f5078d35ed8e344bcba40f35bc95f9176dddb33fc4f2084e04289fa63"}, + {file = "rpds_py-0.13.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80080972e1d000ad0341c7cc58b6855c80bd887675f92871221451d13a975072"}, + {file = "rpds_py-0.13.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:181ee352691c4434eb1c01802e9daa5edcc1007ff15023a320e2693fed6a661b"}, + {file = "rpds_py-0.13.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:d20da6b4c7aa9ee75ad0730beaba15d65157f5beeaca54a038bb968f92bf3ce3"}, + {file = "rpds_py-0.13.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:faa12a9f34671a30ea6bb027f04ec4e1fb8fa3fb3ed030893e729d4d0f3a9791"}, + {file = "rpds_py-0.13.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:7cf241dbb50ea71c2e628ab2a32b5bfcd36e199152fc44e5c1edb0b773f1583e"}, + {file = "rpds_py-0.13.1-cp39-none-win32.whl", hash = "sha256:dab979662da1c9fbb464e310c0b06cb5f1d174d09a462553af78f0bfb3e01920"}, + {file = "rpds_py-0.13.1-cp39-none-win_amd64.whl", hash = "sha256:a2b3c79586636f1fa69a7bd59c87c15fca80c0d34b5c003d57f2f326e5276575"}, + {file = "rpds_py-0.13.1-pp310-pypy310_pp73-macosx_10_7_x86_64.whl", hash = "sha256:5967fa631d0ed9f8511dede08bc943a9727c949d05d1efac4ac82b2938024fb7"}, + {file = "rpds_py-0.13.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:8308a8d49d1354278d5c068c888a58d7158a419b2e4d87c7839ed3641498790c"}, + {file = "rpds_py-0.13.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d0580faeb9def6d0beb7aa666294d5604e569c4e24111ada423cf9936768d95c"}, + {file = "rpds_py-0.13.1-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2da81c1492291c1a90987d76a47c7b2d310661bf7c93a9de0511e27b796a8b46"}, + {file = "rpds_py-0.13.1-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1c9a1dc5e898ce30e2f9c0aa57181cddd4532b22b7780549441d6429d22d3b58"}, + {file = "rpds_py-0.13.1-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f4ae6f423cb7d1c6256b7482025ace2825728f53b7ac58bcd574de6ee9d242c2"}, + {file = "rpds_py-0.13.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc3179e0815827cf963e634095ae5715ee73a5af61defbc8d6ca79f1bdae1d1d"}, + {file = "rpds_py-0.13.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:0d9f8930092558fd15c9e07198625efb698f7cc00b3dc311c83eeec2540226a8"}, + {file = "rpds_py-0.13.1-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:d1d388d2f5f5a6065cf83c54dd12112b7389095669ff395e632003ae8999c6b8"}, + {file = "rpds_py-0.13.1-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:08b335fb0c45f0a9e2478a9ece6a1bfb00b6f4c4780f9be3cf36479c5d8dd374"}, + {file = "rpds_py-0.13.1-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:d11afdc5992bbd7af60ed5eb519873690d921425299f51d80aa3099ed49f2bcc"}, + {file = "rpds_py-0.13.1-pp38-pypy38_pp73-macosx_10_7_x86_64.whl", hash = "sha256:8c1f6c8df23be165eb0cb78f305483d00c6827a191e3a38394c658d5b9c80bbd"}, + {file = "rpds_py-0.13.1-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:528e2afaa56d815d2601b857644aeb395afe7e59212ab0659906dc29ae68d9a6"}, + {file = "rpds_py-0.13.1-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:df2af1180b8eeececf4f819d22cc0668bfadadfd038b19a90bd2fb2ee419ec6f"}, + {file = "rpds_py-0.13.1-pp38-pypy38_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:88956c993a20201744282362e3fd30962a9d86dc4f1dcf2bdb31fab27821b61f"}, + {file = "rpds_py-0.13.1-pp38-pypy38_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ee70ee5f4144a45a9e6169000b5b525d82673d5dab9f7587eccc92794814e7ac"}, + {file = "rpds_py-0.13.1-pp38-pypy38_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c5fd099acaee2325f01281a130a39da08d885e4dedf01b84bf156ec2737d78fe"}, + {file = "rpds_py-0.13.1-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9656a09653b18b80764647d585750df2dff8928e03a706763ab40ec8c4872acc"}, + {file = "rpds_py-0.13.1-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:7ba239bb37663b2b4cd08e703e79e13321512dccd8e5f0e9451d9e53a6b8509a"}, + {file = "rpds_py-0.13.1-pp38-pypy38_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:3f55ae773abd96b1de25fc5c3fb356f491bd19116f8f854ba705beffc1ddc3c5"}, + {file = "rpds_py-0.13.1-pp38-pypy38_pp73-musllinux_1_2_i686.whl", hash = "sha256:f4b15a163448ec79241fb2f1bc5a8ae1a4a304f7a48d948d208a2935b26bf8a5"}, + {file = "rpds_py-0.13.1-pp38-pypy38_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:1a3b2583c86bbfbf417304eeb13400ce7f8725376dc7d3efbf35dc5d7052ad48"}, + {file = "rpds_py-0.13.1-pp39-pypy39_pp73-macosx_10_7_x86_64.whl", hash = "sha256:f1059ca9a51c936c9a8d46fbc2c9a6b4c15ab3f13a97f1ad32f024b39666ba85"}, + {file = "rpds_py-0.13.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:f55601fb58f92e4f4f1d05d80c24cb77505dc42103ddfd63ddfdc51d3da46fa2"}, + {file = "rpds_py-0.13.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fcfd5f91b882eedf8d9601bd21261d6ce0e61a8c66a7152d1f5df08d3f643ab1"}, + {file = "rpds_py-0.13.1-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6574f619e8734140d96c59bfa8a6a6e7a3336820ccd1bfd95ffa610673b650a2"}, + {file = "rpds_py-0.13.1-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a4b9d3f5c48bbe8d9e3758e498b3c34863f2c9b1ac57a4e6310183740e59c980"}, + {file = "rpds_py-0.13.1-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cdd6f8738e1f1d9df5b1603bb03cb30e442710e5672262b95d0f9fcb4edb0dab"}, + {file = "rpds_py-0.13.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a8c2bf286e5d755a075e5e97ba56b3de08cccdad6b323ab0b21cc98875176b03"}, + {file = "rpds_py-0.13.1-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b3d4b390ee70ca9263b331ccfaf9819ee20e90dfd0201a295e23eb64a005dbef"}, + {file = "rpds_py-0.13.1-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:db8d0f0ad92f74feb61c4e4a71f1d573ef37c22ef4dc19cab93e501bfdad8cbd"}, + {file = "rpds_py-0.13.1-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:2abd669a39be69cdfe145927c7eb53a875b157740bf1e2d49e9619fc6f43362e"}, + {file = "rpds_py-0.13.1-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:2c173f529666bab8e3f948b74c6d91afa22ea147e6ebae49a48229d9020a47c4"}, + {file = "rpds_py-0.13.1.tar.gz", hash = "sha256:264f3a5906c62b9df3a00ad35f6da1987d321a053895bd85f9d5c708de5c0fbf"}, ] [[package]] @@ -2684,17 +2685,17 @@ win32 = ["pywin32"] [[package]] name = "setuptools" -version = "68.2.2" +version = "69.0.2" description = "Easily download, build, install, upgrade, and uninstall Python packages" optional = false python-versions = ">=3.8" files = [ - {file = "setuptools-68.2.2-py3-none-any.whl", hash = "sha256:b454a35605876da60632df1a60f736524eb73cc47bbc9f3f1ef1b644de74fd2a"}, - {file = "setuptools-68.2.2.tar.gz", hash = "sha256:4ac1475276d2f1c48684874089fefcd83bd7162ddaafb81fac866ba0db282a87"}, + {file = "setuptools-69.0.2-py3-none-any.whl", hash = "sha256:1e8fdff6797d3865f37397be788a4e3cba233608e9b509382a2777d25ebde7f2"}, + {file = "setuptools-69.0.2.tar.gz", hash = "sha256:735896e78a4742605974de002ac60562d286fa8051a7e2299445e8e8fbb01aa6"}, ] [package.extras] -docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-hoverxref (<2)", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier"] +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"] @@ -3329,13 +3330,13 @@ tooling-extras = ["pyaml (>=23.7.0)", "pypandoc-binary (>=1.11)", "pytest (>=7.4 [[package]] name = "wcwidth" -version = "0.2.10" +version = "0.2.12" description = "Measures the displayed width of unicode strings in a terminal" optional = false python-versions = "*" files = [ - {file = "wcwidth-0.2.10-py2.py3-none-any.whl", hash = "sha256:aec5179002dd0f0d40c456026e74a729661c9d468e1ed64405e3a6c2176ca36f"}, - {file = "wcwidth-0.2.10.tar.gz", hash = "sha256:390c7454101092a6a5e43baad8f83de615463af459201709556b6e4b1c861f97"}, + {file = "wcwidth-0.2.12-py2.py3-none-any.whl", hash = "sha256:f26ec43d96c8cbfed76a5075dac87680124fa84e0855195a6184da9c187f133c"}, + {file = "wcwidth-0.2.12.tar.gz", hash = "sha256:f01c104efdf57971bcb756f054dd58ddec5204dd15fa31d6503ea57947d97c02"}, ] [[package]] @@ -3497,4 +3498,4 @@ virustotal = ["validators"] [metadata] lock-version = "2.0" python-versions = "^3.8" -content-hash = "70fc3f18938b373b0719fd1e6df0e54420a55bd4684d839904929a2136600e61" +content-hash = "5df16df0d7b897e7846066f82b512c2be5dfb4a4af60037534f06ca629f53cab" diff --git a/pymisp/data/misp-objects b/pymisp/data/misp-objects index ca371d4..c18a240 160000 --- a/pymisp/data/misp-objects +++ b/pymisp/data/misp-objects @@ -1 +1 @@ -Subproject commit ca371d456712d0484a7585fbe1bcad4128272512 +Subproject commit c18a240153cbe9ef68e46f05565d08653c2ad103 diff --git a/pyproject.toml b/pyproject.toml index ae561c9..0dca9b1 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "pymisp" -version = "2.4.178" +version = "2.4.179" description = "Python API for MISP." authors = ["Raphaël Vinot "] license = "BSD-2-Clause" @@ -57,7 +57,7 @@ sphinx-autodoc-typehints = {version = "^1.25.2", optional = true} recommonmark = {version = "^0.7.1", optional = true} reportlab = {version = "^4.0.7", optional = true} pyfaup = {version = "^1.2", optional = true} -publicsuffixlist = {version = "^0.10.0.20231109", optional = true} +publicsuffixlist = {version = "^0.10.0.20231122", optional = true} urllib3 = {extras = ["brotli"], version = "*", optional = true} Sphinx = [ {version = "<7.2", python = "<3.9", optional = true}, @@ -81,7 +81,7 @@ ipython = [ {version = "<8.13.0", python = "<3.9"}, {version = "^8.13.0", python = ">=3.9"} ] -jupyterlab = "^4.0.8" +jupyterlab = "^4.0.9" types-requests = "^2.31.0.10" types-python-dateutil = "^2.8.19.14" types-redis = "^4.6.0.10" From c921017cf7988fbe5a2f48dac027ce14f7a9cbea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Vinot?= Date: Wed, 29 Nov 2023 12:35:24 +0100 Subject: [PATCH 07/80] fix: Avoid exception when the malware file name contains a "|" --- pymisp/mispevent.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pymisp/mispevent.py b/pymisp/mispevent.py index d08024c..ef83a2f 100644 --- a/pymisp/mispevent.py +++ b/pymisp/mispevent.py @@ -638,7 +638,7 @@ class MISPAttribute(AbstractMISP): def _prepare_new_malware_sample(self): if '|' in self.value: # Get the filename, ignore the md5, because humans. - self.malware_filename, md5 = self.value.split('|') + self.malware_filename, md5 = self.value.rsplit('|', 1) else: # Assuming the user only passed the filename self.malware_filename = self.value @@ -1665,7 +1665,6 @@ class MISPEvent(AbstractMISP): event_report.pop('sharing_group_id', None) to_return['EventReport'].append(event_report.to_dict()) - return {'Event': to_return} @property From e17fb48ab294c8f51830539c6de380dff5ccd754 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Vinot?= Date: Wed, 29 Nov 2023 12:38:21 +0100 Subject: [PATCH 08/80] chg: Bump deps --- poetry.lock | 183 ++++++++++++++++++++++++------------------------- pyproject.toml | 4 +- 2 files changed, 93 insertions(+), 94 deletions(-) diff --git a/poetry.lock b/poetry.lock index 6f34fc5..126217a 100644 --- a/poetry.lock +++ b/poetry.lock @@ -699,34 +699,34 @@ toml = ["tomli"] [[package]] name = "cryptography" -version = "41.0.5" +version = "41.0.7" description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." optional = false python-versions = ">=3.7" files = [ - {file = "cryptography-41.0.5-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:da6a0ff8f1016ccc7477e6339e1d50ce5f59b88905585f77193ebd5068f1e797"}, - {file = "cryptography-41.0.5-cp37-abi3-macosx_10_12_x86_64.whl", hash = "sha256:b948e09fe5fb18517d99994184854ebd50b57248736fd4c720ad540560174ec5"}, - {file = "cryptography-41.0.5-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d38e6031e113b7421db1de0c1b1f7739564a88f1684c6b89234fbf6c11b75147"}, - {file = "cryptography-41.0.5-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e270c04f4d9b5671ebcc792b3ba5d4488bf7c42c3c241a3748e2599776f29696"}, - {file = "cryptography-41.0.5-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:ec3b055ff8f1dce8e6ef28f626e0972981475173d7973d63f271b29c8a2897da"}, - {file = "cryptography-41.0.5-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:7d208c21e47940369accfc9e85f0de7693d9a5d843c2509b3846b2db170dfd20"}, - {file = "cryptography-41.0.5-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:8254962e6ba1f4d2090c44daf50a547cd5f0bf446dc658a8e5f8156cae0d8548"}, - {file = "cryptography-41.0.5-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:a48e74dad1fb349f3dc1d449ed88e0017d792997a7ad2ec9587ed17405667e6d"}, - {file = "cryptography-41.0.5-cp37-abi3-win32.whl", hash = "sha256:d3977f0e276f6f5bf245c403156673db103283266601405376f075c849a0b936"}, - {file = "cryptography-41.0.5-cp37-abi3-win_amd64.whl", hash = "sha256:73801ac9736741f220e20435f84ecec75ed70eda90f781a148f1bad546963d81"}, - {file = "cryptography-41.0.5-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:3be3ca726e1572517d2bef99a818378bbcf7d7799d5372a46c79c29eb8d166c1"}, - {file = "cryptography-41.0.5-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:e886098619d3815e0ad5790c973afeee2c0e6e04b4da90b88e6bd06e2a0b1b72"}, - {file = "cryptography-41.0.5-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:573eb7128cbca75f9157dcde974781209463ce56b5804983e11a1c462f0f4e88"}, - {file = "cryptography-41.0.5-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:0c327cac00f082013c7c9fb6c46b7cc9fa3c288ca702c74773968173bda421bf"}, - {file = "cryptography-41.0.5-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:227ec057cd32a41c6651701abc0328135e472ed450f47c2766f23267b792a88e"}, - {file = "cryptography-41.0.5-pp38-pypy38_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:22892cc830d8b2c89ea60148227631bb96a7da0c1b722f2aac8824b1b7c0b6b8"}, - {file = "cryptography-41.0.5-pp38-pypy38_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:5a70187954ba7292c7876734183e810b728b4f3965fbe571421cb2434d279179"}, - {file = "cryptography-41.0.5-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:88417bff20162f635f24f849ab182b092697922088b477a7abd6664ddd82291d"}, - {file = "cryptography-41.0.5-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:c707f7afd813478e2019ae32a7c49cd932dd60ab2d2a93e796f68236b7e1fbf1"}, - {file = "cryptography-41.0.5-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:580afc7b7216deeb87a098ef0674d6ee34ab55993140838b14c9b83312b37b86"}, - {file = "cryptography-41.0.5-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:fba1e91467c65fe64a82c689dc6cf58151158993b13eb7a7f3f4b7f395636723"}, - {file = "cryptography-41.0.5-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:0d2a6a598847c46e3e321a7aef8af1436f11c27f1254933746304ff014664d84"}, - {file = "cryptography-41.0.5.tar.gz", hash = "sha256:392cb88b597247177172e02da6b7a63deeff1937fa6fec3bbf902ebd75d97ec7"}, + {file = "cryptography-41.0.7-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:3c78451b78313fa81607fa1b3f1ae0a5ddd8014c38a02d9db0616133987b9cdf"}, + {file = "cryptography-41.0.7-cp37-abi3-macosx_10_12_x86_64.whl", hash = "sha256:928258ba5d6f8ae644e764d0f996d61a8777559f72dfeb2eea7e2fe0ad6e782d"}, + {file = "cryptography-41.0.7-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5a1b41bc97f1ad230a41657d9155113c7521953869ae57ac39ac7f1bb471469a"}, + {file = "cryptography-41.0.7-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:841df4caa01008bad253bce2a6f7b47f86dc9f08df4b433c404def869f590a15"}, + {file = "cryptography-41.0.7-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:5429ec739a29df2e29e15d082f1d9ad683701f0ec7709ca479b3ff2708dae65a"}, + {file = "cryptography-41.0.7-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:43f2552a2378b44869fe8827aa19e69512e3245a219104438692385b0ee119d1"}, + {file = "cryptography-41.0.7-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:af03b32695b24d85a75d40e1ba39ffe7db7ffcb099fe507b39fd41a565f1b157"}, + {file = "cryptography-41.0.7-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:49f0805fc0b2ac8d4882dd52f4a3b935b210935d500b6b805f321addc8177406"}, + {file = "cryptography-41.0.7-cp37-abi3-win32.whl", hash = "sha256:f983596065a18a2183e7f79ab3fd4c475205b839e02cbc0efbbf9666c4b3083d"}, + {file = "cryptography-41.0.7-cp37-abi3-win_amd64.whl", hash = "sha256:90452ba79b8788fa380dfb587cca692976ef4e757b194b093d845e8d99f612f2"}, + {file = "cryptography-41.0.7-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:079b85658ea2f59c4f43b70f8119a52414cdb7be34da5d019a77bf96d473b960"}, + {file = "cryptography-41.0.7-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:b640981bf64a3e978a56167594a0e97db71c89a479da8e175d8bb5be5178c003"}, + {file = "cryptography-41.0.7-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:e3114da6d7f95d2dee7d3f4eec16dacff819740bbab931aff8648cb13c5ff5e7"}, + {file = "cryptography-41.0.7-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:d5ec85080cce7b0513cfd233914eb8b7bbd0633f1d1703aa28d1dd5a72f678ec"}, + {file = "cryptography-41.0.7-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:7a698cb1dac82c35fcf8fe3417a3aaba97de16a01ac914b89a0889d364d2f6be"}, + {file = "cryptography-41.0.7-pp38-pypy38_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:37a138589b12069efb424220bf78eac59ca68b95696fc622b6ccc1c0a197204a"}, + {file = "cryptography-41.0.7-pp38-pypy38_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:68a2dec79deebc5d26d617bfdf6e8aab065a4f34934b22d3b5010df3ba36612c"}, + {file = "cryptography-41.0.7-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:09616eeaef406f99046553b8a40fbf8b1e70795a91885ba4c96a70793de5504a"}, + {file = "cryptography-41.0.7-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:48a0476626da912a44cc078f9893f292f0b3e4c739caf289268168d8f4702a39"}, + {file = "cryptography-41.0.7-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:c7f3201ec47d5207841402594f1d7950879ef890c0c495052fa62f58283fde1a"}, + {file = "cryptography-41.0.7-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:c5ca78485a255e03c32b513f8c2bc39fedb7f5c5f8535545bdc223a03b24f248"}, + {file = "cryptography-41.0.7-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:d6c391c021ab1f7a82da5d8d0b3cee2f4b2c455ec86c8aebbc84837a631ff309"}, + {file = "cryptography-41.0.7.tar.gz", hash = "sha256:13f93ce9bea8016c253b34afc6bd6a75993e5c40672ed5405a9c832f0d4a00bc"}, ] [package.dependencies] @@ -922,13 +922,13 @@ files = [ [[package]] name = "idna" -version = "3.4" +version = "3.6" description = "Internationalized Domain Names in Applications (IDNA)" optional = false python-versions = ">=3.5" files = [ - {file = "idna-3.4-py3-none-any.whl", hash = "sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2"}, - {file = "idna-3.4.tar.gz", hash = "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4"}, + {file = "idna-3.6-py3-none-any.whl", hash = "sha256:c05567e9c24a6b9faaa835c4821bad0590fbb9d5779e7caa6e1cc4978e7eb24f"}, + {file = "idna-3.6.tar.gz", hash = "sha256:9ecdbbd083b06798ae1e86adcbfe8ab1479cf864e4ee30fe4e46a003d12491ca"}, ] [[package]] @@ -992,13 +992,13 @@ files = [ [[package]] name = "ipykernel" -version = "6.27.0" +version = "6.27.1" description = "IPython Kernel for Jupyter" optional = false python-versions = ">=3.8" files = [ - {file = "ipykernel-6.27.0-py3-none-any.whl", hash = "sha256:4388caa3c2cba0a381e20d289545e88a8aef1fe57a884d4c018718ec8c23c121"}, - {file = "ipykernel-6.27.0.tar.gz", hash = "sha256:7f4986f606581be73bfb32dc7a1ac9fa0e804c9be50ddf1c7a119413e982693f"}, + {file = "ipykernel-6.27.1-py3-none-any.whl", hash = "sha256:dab88b47f112f9f7df62236511023c9bdeef67abc73af7c652e4ce4441601686"}, + {file = "ipykernel-6.27.1.tar.gz", hash = "sha256:7d5d594b6690654b4d299edba5e872dc17bb7396a8d0609c97cb7b8a1c605de6"}, ] [package.dependencies] @@ -1064,24 +1064,23 @@ test-extra = ["curio", "matplotlib (!=3.2.0)", "nbformat", "numpy (>=1.21)", "pa [[package]] name = "ipython" -version = "8.17.2" +version = "8.18.1" description = "IPython: Productive Interactive Computing" optional = false python-versions = ">=3.9" files = [ - {file = "ipython-8.17.2-py3-none-any.whl", hash = "sha256:1e4d1d666a023e3c93585ba0d8e962867f7a111af322efff6b9c58062b3e5444"}, - {file = "ipython-8.17.2.tar.gz", hash = "sha256:126bb57e1895594bb0d91ea3090bbd39384f6fe87c3d57fd558d0670f50339bb"}, + {file = "ipython-8.18.1-py3-none-any.whl", hash = "sha256:e8267419d72d81955ec1177f8a29aaa90ac80ad647499201119e2f05e99aa397"}, + {file = "ipython-8.18.1.tar.gz", hash = "sha256:ca6f079bb33457c66e233e4580ebfc4128855b4cf6370dddd73842a9563e8a27"}, ] [package.dependencies] -appnope = {version = "*", markers = "sys_platform == \"darwin\""} colorama = {version = "*", markers = "sys_platform == \"win32\""} decorator = "*" exceptiongroup = {version = "*", markers = "python_version < \"3.11\""} jedi = ">=0.16" matplotlib-inline = "*" pexpect = {version = ">4.3", markers = "sys_platform != \"win32\""} -prompt-toolkit = ">=3.0.30,<3.0.37 || >3.0.37,<3.1.0" +prompt-toolkit = ">=3.0.41,<3.1.0" pygments = ">=2.4.0" stack-data = "*" traitlets = ">=5" @@ -1290,13 +1289,13 @@ test = ["click", "pre-commit", "pytest (>=7.0)", "pytest-asyncio (>=0.19.0)", "p [[package]] name = "jupyter-lsp" -version = "2.2.0" +version = "2.2.1" description = "Multi-Language Server WebSocket proxy for Jupyter Notebook/Lab server" optional = false python-versions = ">=3.8" files = [ - {file = "jupyter-lsp-2.2.0.tar.gz", hash = "sha256:8ebbcb533adb41e5d635eb8fe82956b0aafbf0fd443b6c4bfa906edeeb8635a1"}, - {file = "jupyter_lsp-2.2.0-py3-none-any.whl", hash = "sha256:9e06b8b4f7dd50300b70dd1a78c0c3b0c3d8fa68e0f2d8a5d1fbab62072aca3f"}, + {file = "jupyter-lsp-2.2.1.tar.gz", hash = "sha256:b17fab6d70fe83c8896b0cff59237640038247c196056b43684a0902b6a9e0fb"}, + {file = "jupyter_lsp-2.2.1-py3-none-any.whl", hash = "sha256:17a689910c5e4ae5e7d334b02f31d08ffbe98108f6f658fb05e4304b4345368b"}, ] [package.dependencies] @@ -1305,13 +1304,13 @@ jupyter-server = ">=1.1.2" [[package]] name = "jupyter-server" -version = "2.10.1" +version = "2.11.1" description = "The backend—i.e. core services, APIs, and REST endpoints—to Jupyter web applications." optional = false python-versions = ">=3.8" files = [ - {file = "jupyter_server-2.10.1-py3-none-any.whl", hash = "sha256:20519e355d951fc5e1b6ac5952854fe7620d0cfb56588fa4efe362a758977ed3"}, - {file = "jupyter_server-2.10.1.tar.gz", hash = "sha256:e6da2657a954a7879eed28cc08e0817b01ffd81d7eab8634660397b55f926472"}, + {file = "jupyter_server-2.11.1-py3-none-any.whl", hash = "sha256:4b3a16e3ed16fd202588890f10b8ca589bd3e29405d128beb95935f059441373"}, + {file = "jupyter_server-2.11.1.tar.gz", hash = "sha256:fe80bab96493acf5f7d6cd9a1575af8fbd253dc2591aa4d015131a1e03b5799a"}, ] [package.dependencies] @@ -1577,38 +1576,38 @@ olefile = ">=0.46" [[package]] name = "mypy" -version = "1.7.0" +version = "1.7.1" description = "Optional static typing for Python" optional = false python-versions = ">=3.8" files = [ - {file = "mypy-1.7.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5da84d7bf257fd8f66b4f759a904fd2c5a765f70d8b52dde62b521972a0a2357"}, - {file = "mypy-1.7.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a3637c03f4025f6405737570d6cbfa4f1400eb3c649317634d273687a09ffc2f"}, - {file = "mypy-1.7.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b633f188fc5ae1b6edca39dae566974d7ef4e9aaaae00bc36efe1f855e5173ac"}, - {file = "mypy-1.7.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:d6ed9a3997b90c6f891138e3f83fb8f475c74db4ccaa942a1c7bf99e83a989a1"}, - {file = "mypy-1.7.0-cp310-cp310-win_amd64.whl", hash = "sha256:1fe46e96ae319df21359c8db77e1aecac8e5949da4773c0274c0ef3d8d1268a9"}, - {file = "mypy-1.7.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:df67fbeb666ee8828f675fee724cc2cbd2e4828cc3df56703e02fe6a421b7401"}, - {file = "mypy-1.7.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a79cdc12a02eb526d808a32a934c6fe6df07b05f3573d210e41808020aed8b5d"}, - {file = "mypy-1.7.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f65f385a6f43211effe8c682e8ec3f55d79391f70a201575def73d08db68ead1"}, - {file = "mypy-1.7.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:0e81ffd120ee24959b449b647c4b2fbfcf8acf3465e082b8d58fd6c4c2b27e46"}, - {file = "mypy-1.7.0-cp311-cp311-win_amd64.whl", hash = "sha256:f29386804c3577c83d76520abf18cfcd7d68264c7e431c5907d250ab502658ee"}, - {file = "mypy-1.7.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:87c076c174e2c7ef8ab416c4e252d94c08cd4980a10967754f91571070bf5fbe"}, - {file = "mypy-1.7.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6cb8d5f6d0fcd9e708bb190b224089e45902cacef6f6915481806b0c77f7786d"}, - {file = "mypy-1.7.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d93e76c2256aa50d9c82a88e2f569232e9862c9982095f6d54e13509f01222fc"}, - {file = "mypy-1.7.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:cddee95dea7990e2215576fae95f6b78a8c12f4c089d7e4367564704e99118d3"}, - {file = "mypy-1.7.0-cp312-cp312-win_amd64.whl", hash = "sha256:d01921dbd691c4061a3e2ecdbfbfad029410c5c2b1ee88946bf45c62c6c91210"}, - {file = "mypy-1.7.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:185cff9b9a7fec1f9f7d8352dff8a4c713b2e3eea9c6c4b5ff7f0edf46b91e41"}, - {file = "mypy-1.7.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7a7b1e399c47b18feb6f8ad4a3eef3813e28c1e871ea7d4ea5d444b2ac03c418"}, - {file = "mypy-1.7.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc9fe455ad58a20ec68599139ed1113b21f977b536a91b42bef3ffed5cce7391"}, - {file = "mypy-1.7.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:d0fa29919d2e720c8dbaf07d5578f93d7b313c3e9954c8ec05b6d83da592e5d9"}, - {file = "mypy-1.7.0-cp38-cp38-win_amd64.whl", hash = "sha256:2b53655a295c1ed1af9e96b462a736bf083adba7b314ae775563e3fb4e6795f5"}, - {file = "mypy-1.7.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c1b06b4b109e342f7dccc9efda965fc3970a604db70f8560ddfdee7ef19afb05"}, - {file = "mypy-1.7.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:bf7a2f0a6907f231d5e41adba1a82d7d88cf1f61a70335889412dec99feeb0f8"}, - {file = "mypy-1.7.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:551d4a0cdcbd1d2cccdcc7cb516bb4ae888794929f5b040bb51aae1846062901"}, - {file = "mypy-1.7.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:55d28d7963bef00c330cb6461db80b0b72afe2f3c4e2963c99517cf06454e665"}, - {file = "mypy-1.7.0-cp39-cp39-win_amd64.whl", hash = "sha256:870bd1ffc8a5862e593185a4c169804f2744112b4a7c55b93eb50f48e7a77010"}, - {file = "mypy-1.7.0-py3-none-any.whl", hash = "sha256:96650d9a4c651bc2a4991cf46f100973f656d69edc7faf91844e87fe627f7e96"}, - {file = "mypy-1.7.0.tar.gz", hash = "sha256:1e280b5697202efa698372d2f39e9a6713a0395a756b1c6bd48995f8d72690dc"}, + {file = "mypy-1.7.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:12cce78e329838d70a204293e7b29af9faa3ab14899aec397798a4b41be7f340"}, + {file = "mypy-1.7.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:1484b8fa2c10adf4474f016e09d7a159602f3239075c7bf9f1627f5acf40ad49"}, + {file = "mypy-1.7.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:31902408f4bf54108bbfb2e35369877c01c95adc6192958684473658c322c8a5"}, + {file = "mypy-1.7.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:f2c2521a8e4d6d769e3234350ba7b65ff5d527137cdcde13ff4d99114b0c8e7d"}, + {file = "mypy-1.7.1-cp310-cp310-win_amd64.whl", hash = "sha256:fcd2572dd4519e8a6642b733cd3a8cfc1ef94bafd0c1ceed9c94fe736cb65b6a"}, + {file = "mypy-1.7.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4b901927f16224d0d143b925ce9a4e6b3a758010673eeded9b748f250cf4e8f7"}, + {file = "mypy-1.7.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2f7f6985d05a4e3ce8255396df363046c28bea790e40617654e91ed580ca7c51"}, + {file = "mypy-1.7.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:944bdc21ebd620eafefc090cdf83158393ec2b1391578359776c00de00e8907a"}, + {file = "mypy-1.7.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:9c7ac372232c928fff0645d85f273a726970c014749b924ce5710d7d89763a28"}, + {file = "mypy-1.7.1-cp311-cp311-win_amd64.whl", hash = "sha256:f6efc9bd72258f89a3816e3a98c09d36f079c223aa345c659622f056b760ab42"}, + {file = "mypy-1.7.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:6dbdec441c60699288adf051f51a5d512b0d818526d1dcfff5a41f8cd8b4aaf1"}, + {file = "mypy-1.7.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4fc3d14ee80cd22367caaaf6e014494415bf440980a3045bf5045b525680ac33"}, + {file = "mypy-1.7.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2c6e4464ed5f01dc44dc9821caf67b60a4e5c3b04278286a85c067010653a0eb"}, + {file = "mypy-1.7.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:d9b338c19fa2412f76e17525c1b4f2c687a55b156320acb588df79f2e6fa9fea"}, + {file = "mypy-1.7.1-cp312-cp312-win_amd64.whl", hash = "sha256:204e0d6de5fd2317394a4eff62065614c4892d5a4d1a7ee55b765d7a3d9e3f82"}, + {file = "mypy-1.7.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:84860e06ba363d9c0eeabd45ac0fde4b903ad7aa4f93cd8b648385a888e23200"}, + {file = "mypy-1.7.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:8c5091ebd294f7628eb25ea554852a52058ac81472c921150e3a61cdd68f75a7"}, + {file = "mypy-1.7.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:40716d1f821b89838589e5b3106ebbc23636ffdef5abc31f7cd0266db936067e"}, + {file = "mypy-1.7.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:5cf3f0c5ac72139797953bd50bc6c95ac13075e62dbfcc923571180bebb662e9"}, + {file = "mypy-1.7.1-cp38-cp38-win_amd64.whl", hash = "sha256:78e25b2fd6cbb55ddfb8058417df193f0129cad5f4ee75d1502248e588d9e0d7"}, + {file = "mypy-1.7.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:75c4d2a6effd015786c87774e04331b6da863fc3fc4e8adfc3b40aa55ab516fe"}, + {file = "mypy-1.7.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:2643d145af5292ee956aa0a83c2ce1038a3bdb26e033dadeb2f7066fb0c9abce"}, + {file = "mypy-1.7.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75aa828610b67462ffe3057d4d8a4112105ed211596b750b53cbfe182f44777a"}, + {file = "mypy-1.7.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ee5d62d28b854eb61889cde4e1dbc10fbaa5560cb39780c3995f6737f7e82120"}, + {file = "mypy-1.7.1-cp39-cp39-win_amd64.whl", hash = "sha256:72cf32ce7dd3562373f78bd751f73c96cfb441de147cc2448a92c1a308bd0ca6"}, + {file = "mypy-1.7.1-py3-none-any.whl", hash = "sha256:f7c5d642db47376a0cc130f0de6d055056e010debdaf0707cd2b0fc7e7ef30ea"}, + {file = "mypy-1.7.1.tar.gz", hash = "sha256:fcb6d9afb1b6208b4c712af0dafdc650f518836065df0d4fb1d800f5d6773db2"}, ] [package.dependencies] @@ -1839,13 +1838,13 @@ win-unicode-console = {version = "*", markers = "platform_system == \"Windows\" [[package]] name = "pexpect" -version = "4.8.0" +version = "4.9.0" description = "Pexpect allows easy control of interactive console applications." optional = false python-versions = "*" files = [ - {file = "pexpect-4.8.0-py2.py3-none-any.whl", hash = "sha256:0b48a55dcb3c05f3329815901ea4fc1537514d6ba867a152b581d69ae3710937"}, - {file = "pexpect-4.8.0.tar.gz", hash = "sha256:fc65a43959d153d0114afe13997d439c22823a27cefceb5ff35c2178c6784c0c"}, + {file = "pexpect-4.9.0-py2.py3-none-any.whl", hash = "sha256:7236d1e080e4936be2dc3e326cec0af72acf9212a7e1d060210e70a47e253523"}, + {file = "pexpect-4.9.0.tar.gz", hash = "sha256:ee7d41123f3c9911050ea2c2dac107568dc43b2d3b0c7557a33212c398ead30f"}, ] [package.dependencies] @@ -3082,38 +3081,38 @@ files = [ [[package]] name = "tornado" -version = "6.3.3" +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.3.3-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:502fba735c84450974fec147340016ad928d29f1e91f49be168c0a4c18181e1d"}, - {file = "tornado-6.3.3-cp38-abi3-macosx_10_9_x86_64.whl", hash = "sha256:805d507b1f588320c26f7f097108eb4023bbaa984d63176d1652e184ba24270a"}, - {file = "tornado-6.3.3-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1bd19ca6c16882e4d37368e0152f99c099bad93e0950ce55e71daed74045908f"}, - {file = "tornado-6.3.3-cp38-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7ac51f42808cca9b3613f51ffe2a965c8525cb1b00b7b2d56828b8045354f76a"}, - {file = "tornado-6.3.3-cp38-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:71a8db65160a3c55d61839b7302a9a400074c9c753040455494e2af74e2501f2"}, - {file = "tornado-6.3.3-cp38-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:ceb917a50cd35882b57600709dd5421a418c29ddc852da8bcdab1f0db33406b0"}, - {file = "tornado-6.3.3-cp38-abi3-musllinux_1_1_i686.whl", hash = "sha256:7d01abc57ea0dbb51ddfed477dfe22719d376119844e33c661d873bf9c0e4a16"}, - {file = "tornado-6.3.3-cp38-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:9dc4444c0defcd3929d5c1eb5706cbe1b116e762ff3e0deca8b715d14bf6ec17"}, - {file = "tornado-6.3.3-cp38-abi3-win32.whl", hash = "sha256:65ceca9500383fbdf33a98c0087cb975b2ef3bfb874cb35b8de8740cf7f41bd3"}, - {file = "tornado-6.3.3-cp38-abi3-win_amd64.whl", hash = "sha256:22d3c2fa10b5793da13c807e6fc38ff49a4f6e1e3868b0a6f4164768bb8e20f5"}, - {file = "tornado-6.3.3.tar.gz", hash = "sha256:e7d8db41c0181c80d76c982aacc442c0783a2c54d6400fe028954201a2e032fe"}, + {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 = "traitlets" -version = "5.13.0" +version = "5.14.0" description = "Traitlets Python configuration system" optional = false python-versions = ">=3.8" files = [ - {file = "traitlets-5.13.0-py3-none-any.whl", hash = "sha256:baf991e61542da48fe8aef8b779a9ea0aa38d8a54166ee250d5af5ecf4486619"}, - {file = "traitlets-5.13.0.tar.gz", hash = "sha256:9b232b9430c8f57288c1024b34a8f0251ddcc47268927367a0dd3eeaca40deb5"}, + {file = "traitlets-5.14.0-py3-none-any.whl", hash = "sha256:f14949d23829023013c47df20b4a76ccd1a85effb786dc060f34de7948361b33"}, + {file = "traitlets-5.14.0.tar.gz", hash = "sha256:fcdaa8ac49c04dfa0ed3ee3384ef6dfdb5d6f3741502be247279407679296772"}, ] [package.extras] docs = ["myst-parser", "pydata-sphinx-theme", "sphinx"] -test = ["argcomplete (>=3.0.3)", "mypy (>=1.6.0)", "pre-commit", "pytest (>=7.0,<7.5)", "pytest-mock", "pytest-mypy-testing"] +test = ["argcomplete (>=3.0.3)", "mypy (>=1.7.0)", "pre-commit", "pytest (>=7.0,<7.5)", "pytest-mock", "pytest-mypy-testing"] [[package]] name = "types-click" @@ -3194,13 +3193,13 @@ files = [ [[package]] name = "types-redis" -version = "4.6.0.10" +version = "4.6.0.11" description = "Typing stubs for redis" optional = false python-versions = ">=3.7" files = [ - {file = "types-redis-4.6.0.10.tar.gz", hash = "sha256:aa7fb5f743534500f274ddf11ab1c910aae1020481865a36b799e1d67de2aaf3"}, - {file = "types_redis-4.6.0.10-py3-none-any.whl", hash = "sha256:00f003da884ec3d1d54633186b4cbd587b39782595c5603330cc46a51f9bcf6e"}, + {file = "types-redis-4.6.0.11.tar.gz", hash = "sha256:c8cfc84635183deca2db4a528966c5566445fd3713983f0034fb0f5a09e0890d"}, + {file = "types_redis-4.6.0.11-py3-none-any.whl", hash = "sha256:94fc61118601fb4f79206b33b9f4344acff7ca1d7bba67834987fb0efcf6a770"}, ] [package.dependencies] @@ -3498,4 +3497,4 @@ virustotal = ["validators"] [metadata] lock-version = "2.0" python-versions = "^3.8" -content-hash = "5df16df0d7b897e7846066f82b512c2be5dfb4a4af60037534f06ca629f53cab" +content-hash = "69b4eb7ce67629e2b3f4f085fa17cea8e9faf1b638c9807ae175ec00b1ebca8e" diff --git a/pyproject.toml b/pyproject.toml index 0dca9b1..a692098 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -76,7 +76,7 @@ brotli = ['urllib3'] [tool.poetry.group.dev.dependencies] requests-mock = "^1.11.0" -mypy = "^1.7.0" +mypy = "^1.7.1" ipython = [ {version = "<8.13.0", python = "<3.9"}, {version = "^8.13.0", python = ">=3.9"} @@ -84,7 +84,7 @@ ipython = [ jupyterlab = "^4.0.9" types-requests = "^2.31.0.10" types-python-dateutil = "^2.8.19.14" -types-redis = "^4.6.0.10" +types-redis = "^4.6.0.11" types-Flask = "^1.1.6" pytest-cov = "^4.1.0" From a0f47a4160ef6f1ae02e148c9195db2c84c51aa3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Vinot?= Date: Tue, 5 Dec 2023 00:47:44 +0100 Subject: [PATCH 09/80] chg: Bump deps --- poetry.lock | 267 +++++++++++++++++++++++++------------------------ pyproject.toml | 2 +- 2 files changed, 135 insertions(+), 134 deletions(-) diff --git a/poetry.lock b/poetry.lock index 126217a..1181c8f 100644 --- a/poetry.lock +++ b/poetry.lock @@ -944,20 +944,20 @@ files = [ [[package]] name = "importlib-metadata" -version = "6.8.0" +version = "7.0.0" description = "Read metadata from Python packages" optional = false python-versions = ">=3.8" files = [ - {file = "importlib_metadata-6.8.0-py3-none-any.whl", hash = "sha256:3ebb78df84a805d7698245025b975d9d67053cd94c79245ba4b3eb694abe68bb"}, - {file = "importlib_metadata-6.8.0.tar.gz", hash = "sha256:dbace7892d8c0c4ac1ad096662232f831d4e64f4c4545bd53016a3e9d4654743"}, + {file = "importlib_metadata-7.0.0-py3-none-any.whl", hash = "sha256:d97503976bb81f40a193d41ee6570868479c69d5068651eb039c40d850c59d67"}, + {file = "importlib_metadata-7.0.0.tar.gz", hash = "sha256:7fc841f8b8332803464e5dc1c63a2e59121f46ca186c0e2e182e80bf8c1319f7"}, ] [package.dependencies] zipp = ">=0.5" [package.extras] -docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] +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"] @@ -1206,13 +1206,13 @@ format-nongpl = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339- [[package]] name = "jsonschema-specifications" -version = "2023.11.1" +version = "2023.11.2" description = "The JSON Schema meta-schemas and vocabularies, exposed as a Registry" optional = false python-versions = ">=3.8" files = [ - {file = "jsonschema_specifications-2023.11.1-py3-none-any.whl", hash = "sha256:f596778ab612b3fd29f72ea0d990393d0540a5aab18bf0407a46632eab540779"}, - {file = "jsonschema_specifications-2023.11.1.tar.gz", hash = "sha256:c9b234904ffe02f079bf91b14d79987faa685fd4b39c377a0996954c0090b9ca"}, + {file = "jsonschema_specifications-2023.11.2-py3-none-any.whl", hash = "sha256:e74ba7c0a65e8cb49dc26837d6cfe576557084a8b423ed16a420984228104f93"}, + {file = "jsonschema_specifications-2023.11.2.tar.gz", hash = "sha256:9472fc4fea474cd74bea4a2b190daeccb5a9e4db2ea80efcf7a1b582fc9a81b8"}, ] [package.dependencies] @@ -1304,13 +1304,13 @@ jupyter-server = ">=1.1.2" [[package]] name = "jupyter-server" -version = "2.11.1" +version = "2.11.2" description = "The backend—i.e. core services, APIs, and REST endpoints—to Jupyter web applications." optional = false python-versions = ">=3.8" files = [ - {file = "jupyter_server-2.11.1-py3-none-any.whl", hash = "sha256:4b3a16e3ed16fd202588890f10b8ca589bd3e29405d128beb95935f059441373"}, - {file = "jupyter_server-2.11.1.tar.gz", hash = "sha256:fe80bab96493acf5f7d6cd9a1575af8fbd253dc2591aa4d015131a1e03b5799a"}, + {file = "jupyter_server-2.11.2-py3-none-any.whl", hash = "sha256:0c548151b54bcb516ca466ec628f7f021545be137d01b5467877e87f6fff4374"}, + {file = "jupyter_server-2.11.2.tar.gz", hash = "sha256:0c99f9367b0f24141e527544522430176613f9249849be80504c6d2b955004bb"}, ] [package.dependencies] @@ -1429,17 +1429,18 @@ test = ["hatch", "ipykernel", "openapi-core (>=0.18.0,<0.19.0)", "openapi-spec-v [[package]] name = "lark" -version = "1.1.5" +version = "1.1.8" description = "a modern parsing library" optional = true -python-versions = "*" +python-versions = ">=3.6" files = [ - {file = "lark-1.1.5-py3-none-any.whl", hash = "sha256:8476f9903e93fbde4f6c327f74d79e9b4bd0ed9294c5dfa3164ab8c581b5de2a"}, - {file = "lark-1.1.5.tar.gz", hash = "sha256:4b534eae1f9af5b4ea000bea95776350befe1981658eea3820a01c37e504bb4d"}, + {file = "lark-1.1.8-py3-none-any.whl", hash = "sha256:7d2c221a66a8165f3f81aacb958d26033d40d972fdb70213ab0a2e0627e29c86"}, + {file = "lark-1.1.8.tar.gz", hash = "sha256:7ef424db57f59c1ffd6f0d4c2b705119927f566b68c0fe1942dddcc0e44391a5"}, ] [package.extras] atomic-cache = ["atomicwrites"] +interegular = ["interegular (>=0.3.1,<0.4.0)"] nearley = ["js2py"] regex = ["regex"] @@ -1656,13 +1657,13 @@ test = ["flaky", "ipykernel (>=6.19.3)", "ipython", "ipywidgets", "nbconvert (>= [[package]] name = "nbconvert" -version = "7.11.0" +version = "7.12.0" description = "Converting Jupyter Notebooks" optional = false python-versions = ">=3.8" files = [ - {file = "nbconvert-7.11.0-py3-none-any.whl", hash = "sha256:d1d417b7f34a4e38887f8da5bdfd12372adf3b80f995d57556cb0972c68909fe"}, - {file = "nbconvert-7.11.0.tar.gz", hash = "sha256:abedc01cf543177ffde0bfc2a69726d5a478f6af10a332fc1bf29fcb4f0cf000"}, + {file = "nbconvert-7.12.0-py3-none-any.whl", hash = "sha256:5b6c848194d270cc55fb691169202620d7b52a12fec259508d142ecbe4219310"}, + {file = "nbconvert-7.12.0.tar.gz", hash = "sha256:b1564bd89f69a74cd6398b0362da94db07aafb991b7857216a766204a71612c0"}, ] [package.dependencies] @@ -1941,13 +1942,13 @@ files = [ [[package]] name = "platformdirs" -version = "4.0.0" +version = "4.1.0" description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "platformdirs-4.0.0-py3-none-any.whl", hash = "sha256:118c954d7e949b35437270383a3f2531e99dd93cf7ce4dc8340d3356d30f173b"}, - {file = "platformdirs-4.0.0.tar.gz", hash = "sha256:cb633b2bcf10c51af60beb0ab06d2f1d69064b43abf4c185ca6b28865f3f9731"}, + {file = "platformdirs-4.1.0-py3-none-any.whl", hash = "sha256:11c8f37bcca40db96d8144522d925583bdb7a31f7b0e37e3ed4318400a8e2380"}, + {file = "platformdirs-4.1.0.tar.gz", hash = "sha256:906d548203468492d432bcb294d4bc2fff751bf84971fbb2c10918cc206ee420"}, ] [package.extras] @@ -2442,13 +2443,13 @@ files = [ [[package]] name = "referencing" -version = "0.31.0" +version = "0.31.1" description = "JSON Referencing + Python" optional = false python-versions = ">=3.8" files = [ - {file = "referencing-0.31.0-py3-none-any.whl", hash = "sha256:381b11e53dd93babb55696c71cf42aef2d36b8a150c49bf0bc301e36d536c882"}, - {file = "referencing-0.31.0.tar.gz", hash = "sha256:cc28f2c88fbe7b961a7817a0abc034c09a1e36358f82fedb4ffdf29a25398863"}, + {file = "referencing-0.31.1-py3-none-any.whl", hash = "sha256:c19c4d006f1757e3dd75c4f784d38f8698d87b649c54f9ace14e5e8c9667c01d"}, + {file = "referencing-0.31.1.tar.gz", hash = "sha256:81a1471c68c9d5e3831c30ad1dd9815c45b558e596653db751a2bfdd17b3b9ec"}, ] [package.dependencies] @@ -2541,125 +2542,125 @@ files = [ [[package]] name = "rpds-py" -version = "0.13.1" +version = "0.13.2" description = "Python bindings to Rust's persistent data structures (rpds)" optional = false python-versions = ">=3.8" files = [ - {file = "rpds_py-0.13.1-cp310-cp310-macosx_10_7_x86_64.whl", hash = "sha256:83feb0f682d75a09ddc11aa37ba5c07dd9b824b22915207f6176ea458474ff75"}, - {file = "rpds_py-0.13.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fa84bbe22ffa108f91631935c28a623001e335d66e393438258501e618fb0dde"}, - {file = "rpds_py-0.13.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e04f8c76b8d5c70695b4e8f1d0b391d8ef91df00ef488c6c1ffb910176459bc6"}, - {file = "rpds_py-0.13.1-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:032c242a595629aacace44128f9795110513ad27217b091e834edec2fb09e800"}, - {file = "rpds_py-0.13.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:91276caef95556faeb4b8f09fe4439670d3d6206fee78d47ddb6e6de837f0b4d"}, - {file = "rpds_py-0.13.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d22f2cb82e0b40e427a74a93c9a4231335bbc548aed79955dde0b64ea7f88146"}, - {file = "rpds_py-0.13.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:63c9e2794329ef070844ff9bfc012004aeddc0468dc26970953709723f76c8a5"}, - {file = "rpds_py-0.13.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c797ea56f36c6f248656f0223b11307fdf4a1886f3555eba371f34152b07677f"}, - {file = "rpds_py-0.13.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:82dbcd6463e580bcfb7561cece35046aaabeac5a9ddb775020160b14e6c58a5d"}, - {file = "rpds_py-0.13.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:736817dbbbd030a69a1faf5413a319976c9c8ba8cdcfa98c022d3b6b2e01eca6"}, - {file = "rpds_py-0.13.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:1f36a1e80ef4ed1996445698fd91e0d3e54738bf597c9995118b92da537d7a28"}, - {file = "rpds_py-0.13.1-cp310-none-win32.whl", hash = "sha256:4f13d3f6585bd07657a603780e99beda96a36c86acaba841f131e81393958336"}, - {file = "rpds_py-0.13.1-cp310-none-win_amd64.whl", hash = "sha256:545e94c84575057d3d5c62634611858dac859702b1519b6ffc58eca7fb1adfcf"}, - {file = "rpds_py-0.13.1-cp311-cp311-macosx_10_7_x86_64.whl", hash = "sha256:6bfe72b249264cc1ff2f3629be240d7d2fdc778d9d298087cdec8524c91cd11f"}, - {file = "rpds_py-0.13.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:edc91c50e17f5cd945d821f0f1af830522dba0c10267c3aab186dc3dbaab8def"}, - {file = "rpds_py-0.13.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2eca04a365be380ca1f8fa48b334462e19e3382c0bb7386444d8ca43aa01c481"}, - {file = "rpds_py-0.13.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3e3ac5b602fea378243f993d8b707189f9061e55ebb4e56cb9fdef8166060f28"}, - {file = "rpds_py-0.13.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dfb5d2ab183c0efe5e7b8917e4eaa2e837aacafad8a69b89aa6bc81550eed857"}, - {file = "rpds_py-0.13.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d9793d46d3e6522ae58e9321032827c9c0df1e56cbe5d3de965facb311aed6aa"}, - {file = "rpds_py-0.13.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9cd935c0220d012a27c20135c140f9cdcbc6249d5954345c81bfb714071b985c"}, - {file = "rpds_py-0.13.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:37b08df45f02ff1866043b95096cbe91ac99de05936dd09d6611987a82a3306a"}, - {file = "rpds_py-0.13.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:ad666a904212aa9a6c77da7dce9d5170008cda76b7776e6731928b3f8a0d40fa"}, - {file = "rpds_py-0.13.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:8a6ad8429340e0a4de89353447c6441329def3632e7b2293a7d6e873217d3c2b"}, - {file = "rpds_py-0.13.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:7c40851b659d958c5245c1236e34f0d065cc53dca8d978b49a032c8e0adfda6e"}, - {file = "rpds_py-0.13.1-cp311-none-win32.whl", hash = "sha256:4145172ab59b6c27695db6d78d040795f635cba732cead19c78cede74800949a"}, - {file = "rpds_py-0.13.1-cp311-none-win_amd64.whl", hash = "sha256:46a07a258bda12270de02b34c4884f200f864bba3dcd6e3a37fef36a168b859d"}, - {file = "rpds_py-0.13.1-cp312-cp312-macosx_10_7_x86_64.whl", hash = "sha256:ba4432301ad7eeb1b00848cf46fae0e5fecfd18a8cb5fdcf856c67985f79ecc7"}, - {file = "rpds_py-0.13.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d22e0660de24bd8e9ac82f4230a22a5fe4e397265709289d61d5fb333839ba50"}, - {file = "rpds_py-0.13.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76a8374b294e4ccb39ccaf11d39a0537ed107534139c00b4393ca3b542cc66e5"}, - {file = "rpds_py-0.13.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7d152ec7bb431040af2500e01436c9aa0d993f243346f0594a15755016bf0be1"}, - {file = "rpds_py-0.13.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:74a2044b870df7c9360bb3ce7e12f9ddf8e72e49cd3a353a1528cbf166ad2383"}, - {file = "rpds_py-0.13.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:960e7e460fda2d0af18c75585bbe0c99f90b8f09963844618a621b804f8c3abe"}, - {file = "rpds_py-0.13.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:37f79f4f1f06cc96151f4a187528c3fd4a7e1065538a4af9eb68c642365957f7"}, - {file = "rpds_py-0.13.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:cd4ea56c9542ad0091dfdef3e8572ae7a746e1e91eb56c9e08b8d0808b40f1d1"}, - {file = "rpds_py-0.13.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:0290712eb5603a725769b5d857f7cf15cf6ca93dda3128065bbafe6fdb709beb"}, - {file = "rpds_py-0.13.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:0b70c1f800059c92479dc94dda41288fd6607f741f9b1b8f89a21a86428f6383"}, - {file = "rpds_py-0.13.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:3dd5fb7737224e1497c886fb3ca681c15d9c00c76171f53b3c3cc8d16ccfa7fb"}, - {file = "rpds_py-0.13.1-cp312-none-win32.whl", hash = "sha256:74be3b215a5695690a0f1a9f68b1d1c93f8caad52e23242fcb8ba56aaf060281"}, - {file = "rpds_py-0.13.1-cp312-none-win_amd64.whl", hash = "sha256:f47eef55297799956464efc00c74ae55c48a7b68236856d56183fe1ddf866205"}, - {file = "rpds_py-0.13.1-cp38-cp38-macosx_10_7_x86_64.whl", hash = "sha256:e4a45ba34f904062c63049a760790c6a2fa7a4cc4bd160d8af243b12371aaa05"}, - {file = "rpds_py-0.13.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:20147996376be452cd82cd6c17701daba69a849dc143270fa10fe067bb34562a"}, - {file = "rpds_py-0.13.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42b9535aa22ab023704cfc6533e968f7e420affe802d85e956d8a7b4c0b0b5ea"}, - {file = "rpds_py-0.13.1-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d4fa1eeb9bea6d9b64ac91ec51ee94cc4fc744955df5be393e1c923c920db2b0"}, - {file = "rpds_py-0.13.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2b2415d5a7b7ee96aa3a54d4775c1fec140476a17ee12353806297e900eaeddc"}, - {file = "rpds_py-0.13.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:577d40a72550eac1386b77b43836151cb61ff6700adacda2ad4d883ca5a0b6f2"}, - {file = "rpds_py-0.13.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:af2d1648eb625a460eee07d3e1ea3a4a6e84a1fb3a107f6a8e95ac19f7dcce67"}, - {file = "rpds_py-0.13.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5b769396eb358d6b55dbf78f3f7ca631ca1b2fe02136faad5af74f0111b4b6b7"}, - {file = "rpds_py-0.13.1-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:249c8e0055ca597707d71c5ad85fd2a1c8fdb99386a8c6c257e1b47b67a9bec1"}, - {file = "rpds_py-0.13.1-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:fe30ef31172bdcf946502a945faad110e8fff88c32c4bec9a593df0280e64d8a"}, - {file = "rpds_py-0.13.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:2647192facf63be9ed2d7a49ceb07efe01dc6cfb083bd2cc53c418437400cb99"}, - {file = "rpds_py-0.13.1-cp38-none-win32.whl", hash = "sha256:4011d5c854aa804c833331d38a2b6f6f2fe58a90c9f615afdb7aa7cf9d31f721"}, - {file = "rpds_py-0.13.1-cp38-none-win_amd64.whl", hash = "sha256:7cfae77da92a20f56cf89739a557b76e5c6edc094f6ad5c090b9e15fbbfcd1a4"}, - {file = "rpds_py-0.13.1-cp39-cp39-macosx_10_7_x86_64.whl", hash = "sha256:e9be1f7c5f9673616f875299339984da9447a40e3aea927750c843d6e5e2e029"}, - {file = "rpds_py-0.13.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:839676475ac2ccd1532d36af3d10d290a2ca149b702ed464131e450a767550df"}, - {file = "rpds_py-0.13.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a90031658805c63fe488f8e9e7a88b260ea121ba3ee9cdabcece9c9ddb50da39"}, - {file = "rpds_py-0.13.1-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8ba9fbc5d6e36bfeb5292530321cc56c4ef3f98048647fabd8f57543c34174ec"}, - {file = "rpds_py-0.13.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:08832078767545c5ee12561ce980714e1e4c6619b5b1e9a10248de60cddfa1fd"}, - {file = "rpds_py-0.13.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:19f5aa7f5078d35ed8e344bcba40f35bc95f9176dddb33fc4f2084e04289fa63"}, - {file = "rpds_py-0.13.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80080972e1d000ad0341c7cc58b6855c80bd887675f92871221451d13a975072"}, - {file = "rpds_py-0.13.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:181ee352691c4434eb1c01802e9daa5edcc1007ff15023a320e2693fed6a661b"}, - {file = "rpds_py-0.13.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:d20da6b4c7aa9ee75ad0730beaba15d65157f5beeaca54a038bb968f92bf3ce3"}, - {file = "rpds_py-0.13.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:faa12a9f34671a30ea6bb027f04ec4e1fb8fa3fb3ed030893e729d4d0f3a9791"}, - {file = "rpds_py-0.13.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:7cf241dbb50ea71c2e628ab2a32b5bfcd36e199152fc44e5c1edb0b773f1583e"}, - {file = "rpds_py-0.13.1-cp39-none-win32.whl", hash = "sha256:dab979662da1c9fbb464e310c0b06cb5f1d174d09a462553af78f0bfb3e01920"}, - {file = "rpds_py-0.13.1-cp39-none-win_amd64.whl", hash = "sha256:a2b3c79586636f1fa69a7bd59c87c15fca80c0d34b5c003d57f2f326e5276575"}, - {file = "rpds_py-0.13.1-pp310-pypy310_pp73-macosx_10_7_x86_64.whl", hash = "sha256:5967fa631d0ed9f8511dede08bc943a9727c949d05d1efac4ac82b2938024fb7"}, - {file = "rpds_py-0.13.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:8308a8d49d1354278d5c068c888a58d7158a419b2e4d87c7839ed3641498790c"}, - {file = "rpds_py-0.13.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d0580faeb9def6d0beb7aa666294d5604e569c4e24111ada423cf9936768d95c"}, - {file = "rpds_py-0.13.1-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2da81c1492291c1a90987d76a47c7b2d310661bf7c93a9de0511e27b796a8b46"}, - {file = "rpds_py-0.13.1-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1c9a1dc5e898ce30e2f9c0aa57181cddd4532b22b7780549441d6429d22d3b58"}, - {file = "rpds_py-0.13.1-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f4ae6f423cb7d1c6256b7482025ace2825728f53b7ac58bcd574de6ee9d242c2"}, - {file = "rpds_py-0.13.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc3179e0815827cf963e634095ae5715ee73a5af61defbc8d6ca79f1bdae1d1d"}, - {file = "rpds_py-0.13.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:0d9f8930092558fd15c9e07198625efb698f7cc00b3dc311c83eeec2540226a8"}, - {file = "rpds_py-0.13.1-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:d1d388d2f5f5a6065cf83c54dd12112b7389095669ff395e632003ae8999c6b8"}, - {file = "rpds_py-0.13.1-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:08b335fb0c45f0a9e2478a9ece6a1bfb00b6f4c4780f9be3cf36479c5d8dd374"}, - {file = "rpds_py-0.13.1-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:d11afdc5992bbd7af60ed5eb519873690d921425299f51d80aa3099ed49f2bcc"}, - {file = "rpds_py-0.13.1-pp38-pypy38_pp73-macosx_10_7_x86_64.whl", hash = "sha256:8c1f6c8df23be165eb0cb78f305483d00c6827a191e3a38394c658d5b9c80bbd"}, - {file = "rpds_py-0.13.1-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:528e2afaa56d815d2601b857644aeb395afe7e59212ab0659906dc29ae68d9a6"}, - {file = "rpds_py-0.13.1-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:df2af1180b8eeececf4f819d22cc0668bfadadfd038b19a90bd2fb2ee419ec6f"}, - {file = "rpds_py-0.13.1-pp38-pypy38_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:88956c993a20201744282362e3fd30962a9d86dc4f1dcf2bdb31fab27821b61f"}, - {file = "rpds_py-0.13.1-pp38-pypy38_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ee70ee5f4144a45a9e6169000b5b525d82673d5dab9f7587eccc92794814e7ac"}, - {file = "rpds_py-0.13.1-pp38-pypy38_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c5fd099acaee2325f01281a130a39da08d885e4dedf01b84bf156ec2737d78fe"}, - {file = "rpds_py-0.13.1-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9656a09653b18b80764647d585750df2dff8928e03a706763ab40ec8c4872acc"}, - {file = "rpds_py-0.13.1-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:7ba239bb37663b2b4cd08e703e79e13321512dccd8e5f0e9451d9e53a6b8509a"}, - {file = "rpds_py-0.13.1-pp38-pypy38_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:3f55ae773abd96b1de25fc5c3fb356f491bd19116f8f854ba705beffc1ddc3c5"}, - {file = "rpds_py-0.13.1-pp38-pypy38_pp73-musllinux_1_2_i686.whl", hash = "sha256:f4b15a163448ec79241fb2f1bc5a8ae1a4a304f7a48d948d208a2935b26bf8a5"}, - {file = "rpds_py-0.13.1-pp38-pypy38_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:1a3b2583c86bbfbf417304eeb13400ce7f8725376dc7d3efbf35dc5d7052ad48"}, - {file = "rpds_py-0.13.1-pp39-pypy39_pp73-macosx_10_7_x86_64.whl", hash = "sha256:f1059ca9a51c936c9a8d46fbc2c9a6b4c15ab3f13a97f1ad32f024b39666ba85"}, - {file = "rpds_py-0.13.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:f55601fb58f92e4f4f1d05d80c24cb77505dc42103ddfd63ddfdc51d3da46fa2"}, - {file = "rpds_py-0.13.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fcfd5f91b882eedf8d9601bd21261d6ce0e61a8c66a7152d1f5df08d3f643ab1"}, - {file = "rpds_py-0.13.1-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6574f619e8734140d96c59bfa8a6a6e7a3336820ccd1bfd95ffa610673b650a2"}, - {file = "rpds_py-0.13.1-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a4b9d3f5c48bbe8d9e3758e498b3c34863f2c9b1ac57a4e6310183740e59c980"}, - {file = "rpds_py-0.13.1-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cdd6f8738e1f1d9df5b1603bb03cb30e442710e5672262b95d0f9fcb4edb0dab"}, - {file = "rpds_py-0.13.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a8c2bf286e5d755a075e5e97ba56b3de08cccdad6b323ab0b21cc98875176b03"}, - {file = "rpds_py-0.13.1-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b3d4b390ee70ca9263b331ccfaf9819ee20e90dfd0201a295e23eb64a005dbef"}, - {file = "rpds_py-0.13.1-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:db8d0f0ad92f74feb61c4e4a71f1d573ef37c22ef4dc19cab93e501bfdad8cbd"}, - {file = "rpds_py-0.13.1-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:2abd669a39be69cdfe145927c7eb53a875b157740bf1e2d49e9619fc6f43362e"}, - {file = "rpds_py-0.13.1-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:2c173f529666bab8e3f948b74c6d91afa22ea147e6ebae49a48229d9020a47c4"}, - {file = "rpds_py-0.13.1.tar.gz", hash = "sha256:264f3a5906c62b9df3a00ad35f6da1987d321a053895bd85f9d5c708de5c0fbf"}, + {file = "rpds_py-0.13.2-cp310-cp310-macosx_10_7_x86_64.whl", hash = "sha256:1ceebd0ae4f3e9b2b6b553b51971921853ae4eebf3f54086be0565d59291e53d"}, + {file = "rpds_py-0.13.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:46e1ed994a0920f350a4547a38471217eb86f57377e9314fbaaa329b71b7dfe3"}, + {file = "rpds_py-0.13.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ee353bb51f648924926ed05e0122b6a0b1ae709396a80eb583449d5d477fcdf7"}, + {file = "rpds_py-0.13.2-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:530190eb0cd778363bbb7596612ded0bb9fef662daa98e9d92a0419ab27ae914"}, + {file = "rpds_py-0.13.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:29d311e44dd16d2434d5506d57ef4d7036544fc3c25c14b6992ef41f541b10fb"}, + {file = "rpds_py-0.13.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2e72f750048b32d39e87fc85c225c50b2a6715034848dbb196bf3348aa761fa1"}, + {file = "rpds_py-0.13.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:db09b98c7540df69d4b47218da3fbd7cb466db0fb932e971c321f1c76f155266"}, + {file = "rpds_py-0.13.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2ac26f50736324beb0282c819668328d53fc38543fa61eeea2c32ea8ea6eab8d"}, + {file = "rpds_py-0.13.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:12ecf89bd54734c3c2c79898ae2021dca42750c7bcfb67f8fb3315453738ac8f"}, + {file = "rpds_py-0.13.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:3a44c8440183b43167fd1a0819e8356692bf5db1ad14ce140dbd40a1485f2dea"}, + {file = "rpds_py-0.13.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:bcef4f2d3dc603150421de85c916da19471f24d838c3c62a4f04c1eb511642c1"}, + {file = "rpds_py-0.13.2-cp310-none-win32.whl", hash = "sha256:ee6faebb265e28920a6f23a7d4c362414b3f4bb30607141d718b991669e49ddc"}, + {file = "rpds_py-0.13.2-cp310-none-win_amd64.whl", hash = "sha256:ac96d67b37f28e4b6ecf507c3405f52a40658c0a806dffde624a8fcb0314d5fd"}, + {file = "rpds_py-0.13.2-cp311-cp311-macosx_10_7_x86_64.whl", hash = "sha256:b5f6328e8e2ae8238fc767703ab7b95785521c42bb2b8790984e3477d7fa71ad"}, + {file = "rpds_py-0.13.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:729408136ef8d45a28ee9a7411917c9e3459cf266c7e23c2f7d4bb8ef9e0da42"}, + {file = "rpds_py-0.13.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:65cfed9c807c27dee76407e8bb29e6f4e391e436774bcc769a037ff25ad8646e"}, + {file = "rpds_py-0.13.2-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:aefbdc934115d2f9278f153952003ac52cd2650e7313750390b334518c589568"}, + {file = "rpds_py-0.13.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d48db29bd47814671afdd76c7652aefacc25cf96aad6daefa82d738ee87461e2"}, + {file = "rpds_py-0.13.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3c55d7f2d817183d43220738270efd3ce4e7a7b7cbdaefa6d551ed3d6ed89190"}, + {file = "rpds_py-0.13.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6aadae3042f8e6db3376d9e91f194c606c9a45273c170621d46128f35aef7cd0"}, + {file = "rpds_py-0.13.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5feae2f9aa7270e2c071f488fab256d768e88e01b958f123a690f1cc3061a09c"}, + {file = "rpds_py-0.13.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:51967a67ea0d7b9b5cd86036878e2d82c0b6183616961c26d825b8c994d4f2c8"}, + {file = "rpds_py-0.13.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:4d0c10d803549427f427085ed7aebc39832f6e818a011dcd8785e9c6a1ba9b3e"}, + {file = "rpds_py-0.13.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:603d5868f7419081d616dab7ac3cfa285296735e7350f7b1e4f548f6f953ee7d"}, + {file = "rpds_py-0.13.2-cp311-none-win32.whl", hash = "sha256:b8996ffb60c69f677245f5abdbcc623e9442bcc91ed81b6cd6187129ad1fa3e7"}, + {file = "rpds_py-0.13.2-cp311-none-win_amd64.whl", hash = "sha256:5379e49d7e80dca9811b36894493d1c1ecb4c57de05c36f5d0dd09982af20211"}, + {file = "rpds_py-0.13.2-cp312-cp312-macosx_10_7_x86_64.whl", hash = "sha256:8a776a29b77fe0cc28fedfd87277b0d0f7aa930174b7e504d764e0b43a05f381"}, + {file = "rpds_py-0.13.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2a1472956c5bcc49fb0252b965239bffe801acc9394f8b7c1014ae9258e4572b"}, + {file = "rpds_py-0.13.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f252dfb4852a527987a9156cbcae3022a30f86c9d26f4f17b8c967d7580d65d2"}, + {file = "rpds_py-0.13.2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f0d320e70b6b2300ff6029e234e79fe44e9dbbfc7b98597ba28e054bd6606a57"}, + {file = "rpds_py-0.13.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ade2ccb937060c299ab0dfb2dea3d2ddf7e098ed63ee3d651ebfc2c8d1e8632a"}, + {file = "rpds_py-0.13.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b9d121be0217787a7d59a5c6195b0842d3f701007333426e5154bf72346aa658"}, + {file = "rpds_py-0.13.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8fa6bd071ec6d90f6e7baa66ae25820d57a8ab1b0a3c6d3edf1834d4b26fafa2"}, + {file = "rpds_py-0.13.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c918621ee0a3d1fe61c313f2489464f2ae3d13633e60f520a8002a5e910982ee"}, + {file = "rpds_py-0.13.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:25b28b3d33ec0a78e944aaaed7e5e2a94ac811bcd68b557ca48a0c30f87497d2"}, + {file = "rpds_py-0.13.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:31e220a040b89a01505128c2f8a59ee74732f666439a03e65ccbf3824cdddae7"}, + {file = "rpds_py-0.13.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:15253fff410873ebf3cfba1cc686a37711efcd9b8cb30ea21bb14a973e393f60"}, + {file = "rpds_py-0.13.2-cp312-none-win32.whl", hash = "sha256:b981a370f8f41c4024c170b42fbe9e691ae2dbc19d1d99151a69e2c84a0d194d"}, + {file = "rpds_py-0.13.2-cp312-none-win_amd64.whl", hash = "sha256:4c4e314d36d4f31236a545696a480aa04ea170a0b021e9a59ab1ed94d4c3ef27"}, + {file = "rpds_py-0.13.2-cp38-cp38-macosx_10_7_x86_64.whl", hash = "sha256:80e5acb81cb49fd9f2d5c08f8b74ffff14ee73b10ca88297ab4619e946bcb1e1"}, + {file = "rpds_py-0.13.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:efe093acc43e869348f6f2224df7f452eab63a2c60a6c6cd6b50fd35c4e075ba"}, + {file = "rpds_py-0.13.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8c2a61c0e4811012b0ba9f6cdcb4437865df5d29eab5d6018ba13cee1c3064a0"}, + {file = "rpds_py-0.13.2-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:751758d9dd04d548ec679224cc00e3591f5ebf1ff159ed0d4aba6a0746352452"}, + {file = "rpds_py-0.13.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6ba8858933f0c1a979781272a5f65646fca8c18c93c99c6ddb5513ad96fa54b1"}, + {file = "rpds_py-0.13.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bfdfbe6a36bc3059fff845d64c42f2644cf875c65f5005db54f90cdfdf1df815"}, + {file = "rpds_py-0.13.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aa0379c1935c44053c98826bc99ac95f3a5355675a297ac9ce0dfad0ce2d50ca"}, + {file = "rpds_py-0.13.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d5593855b5b2b73dd8413c3fdfa5d95b99d657658f947ba2c4318591e745d083"}, + {file = "rpds_py-0.13.2-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:2a7bef6977043673750a88da064fd513f89505111014b4e00fbdd13329cd4e9a"}, + {file = "rpds_py-0.13.2-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:3ab96754d23372009638a402a1ed12a27711598dd49d8316a22597141962fe66"}, + {file = "rpds_py-0.13.2-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:e06cfea0ece444571d24c18ed465bc93afb8c8d8d74422eb7026662f3d3f779b"}, + {file = "rpds_py-0.13.2-cp38-none-win32.whl", hash = "sha256:5493569f861fb7b05af6d048d00d773c6162415ae521b7010197c98810a14cab"}, + {file = "rpds_py-0.13.2-cp38-none-win_amd64.whl", hash = "sha256:b07501b720cf060c5856f7b5626e75b8e353b5f98b9b354a21eb4bfa47e421b1"}, + {file = "rpds_py-0.13.2-cp39-cp39-macosx_10_7_x86_64.whl", hash = "sha256:881df98f0a8404d32b6de0fd33e91c1b90ed1516a80d4d6dc69d414b8850474c"}, + {file = "rpds_py-0.13.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:d79c159adea0f1f4617f54aa156568ac69968f9ef4d1e5fefffc0a180830308e"}, + {file = "rpds_py-0.13.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:38d4f822ee2f338febcc85aaa2547eb5ba31ba6ff68d10b8ec988929d23bb6b4"}, + {file = "rpds_py-0.13.2-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5d75d6d220d55cdced2f32cc22f599475dbe881229aeddba6c79c2e9df35a2b3"}, + {file = "rpds_py-0.13.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5d97e9ae94fb96df1ee3cb09ca376c34e8a122f36927230f4c8a97f469994bff"}, + {file = "rpds_py-0.13.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:67a429520e97621a763cf9b3ba27574779c4e96e49a27ff8a1aa99ee70beb28a"}, + {file = "rpds_py-0.13.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:188435794405c7f0573311747c85a96b63c954a5f2111b1df8018979eca0f2f0"}, + {file = "rpds_py-0.13.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:38f9bf2ad754b4a45b8210a6c732fe876b8a14e14d5992a8c4b7c1ef78740f53"}, + {file = "rpds_py-0.13.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:a6ba2cb7d676e9415b9e9ac7e2aae401dc1b1e666943d1f7bc66223d3d73467b"}, + {file = "rpds_py-0.13.2-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:eaffbd8814bb1b5dc3ea156a4c5928081ba50419f9175f4fc95269e040eff8f0"}, + {file = "rpds_py-0.13.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:5a4c1058cdae6237d97af272b326e5f78ee7ee3bbffa6b24b09db4d828810468"}, + {file = "rpds_py-0.13.2-cp39-none-win32.whl", hash = "sha256:b5267feb19070bef34b8dea27e2b504ebd9d31748e3ecacb3a4101da6fcb255c"}, + {file = "rpds_py-0.13.2-cp39-none-win_amd64.whl", hash = "sha256:ddf23960cb42b69bce13045d5bc66f18c7d53774c66c13f24cf1b9c144ba3141"}, + {file = "rpds_py-0.13.2-pp310-pypy310_pp73-macosx_10_7_x86_64.whl", hash = "sha256:97163a1ab265a1073a6372eca9f4eeb9f8c6327457a0b22ddfc4a17dcd613e74"}, + {file = "rpds_py-0.13.2-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:25ea41635d22b2eb6326f58e608550e55d01df51b8a580ea7e75396bafbb28e9"}, + {file = "rpds_py-0.13.2-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76d59d4d451ba77f08cb4cd9268dec07be5bc65f73666302dbb5061989b17198"}, + {file = "rpds_py-0.13.2-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e7c564c58cf8f248fe859a4f0fe501b050663f3d7fbc342172f259124fb59933"}, + {file = "rpds_py-0.13.2-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:61dbc1e01dc0c5875da2f7ae36d6e918dc1b8d2ce04e871793976594aad8a57a"}, + {file = "rpds_py-0.13.2-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fdb82eb60d31b0c033a8e8ee9f3fc7dfbaa042211131c29da29aea8531b4f18f"}, + {file = "rpds_py-0.13.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d204957169f0b3511fb95395a9da7d4490fb361763a9f8b32b345a7fe119cb45"}, + {file = "rpds_py-0.13.2-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c45008ca79bad237cbc03c72bc5205e8c6f66403773929b1b50f7d84ef9e4d07"}, + {file = "rpds_py-0.13.2-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:79bf58c08f0756adba691d480b5a20e4ad23f33e1ae121584cf3a21717c36dfa"}, + {file = "rpds_py-0.13.2-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:e86593bf8637659e6a6ed58854b6c87ec4e9e45ee8a4adfd936831cef55c2d21"}, + {file = "rpds_py-0.13.2-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:d329896c40d9e1e5c7715c98529e4a188a1f2df51212fd65102b32465612b5dc"}, + {file = "rpds_py-0.13.2-pp38-pypy38_pp73-macosx_10_7_x86_64.whl", hash = "sha256:4a5375c5fff13f209527cd886dc75394f040c7d1ecad0a2cb0627f13ebe78a12"}, + {file = "rpds_py-0.13.2-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:06d218e4464d31301e943b65b2c6919318ea6f69703a351961e1baaf60347276"}, + {file = "rpds_py-0.13.2-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c1f41d32a2ddc5a94df4b829b395916a4b7f103350fa76ba6de625fcb9e773ac"}, + {file = "rpds_py-0.13.2-pp38-pypy38_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6bc568b05e02cd612be53900c88aaa55012e744930ba2eeb56279db4c6676eb3"}, + {file = "rpds_py-0.13.2-pp38-pypy38_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9d94d78418203904730585efa71002286ac4c8ac0689d0eb61e3c465f9e608ff"}, + {file = "rpds_py-0.13.2-pp38-pypy38_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bed0252c85e21cf73d2d033643c945b460d6a02fc4a7d644e3b2d6f5f2956c64"}, + {file = "rpds_py-0.13.2-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:244e173bb6d8f3b2f0c4d7370a1aa341f35da3e57ffd1798e5b2917b91731fd3"}, + {file = "rpds_py-0.13.2-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:7f55cd9cf1564b7b03f238e4c017ca4794c05b01a783e9291065cb2858d86ce4"}, + {file = "rpds_py-0.13.2-pp38-pypy38_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:f03a1b3a4c03e3e0161642ac5367f08479ab29972ea0ffcd4fa18f729cd2be0a"}, + {file = "rpds_py-0.13.2-pp38-pypy38_pp73-musllinux_1_2_i686.whl", hash = "sha256:f5f4424cb87a20b016bfdc157ff48757b89d2cc426256961643d443c6c277007"}, + {file = "rpds_py-0.13.2-pp38-pypy38_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:c82bbf7e03748417c3a88c1b0b291288ce3e4887a795a3addaa7a1cfd9e7153e"}, + {file = "rpds_py-0.13.2-pp39-pypy39_pp73-macosx_10_7_x86_64.whl", hash = "sha256:c0095b8aa3e432e32d372e9a7737e65b58d5ed23b9620fea7cb81f17672f1fa1"}, + {file = "rpds_py-0.13.2-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:4c2d26aa03d877c9730bf005621c92da263523a1e99247590abbbe252ccb7824"}, + {file = "rpds_py-0.13.2-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:96f2975fb14f39c5fe75203f33dd3010fe37d1c4e33177feef1107b5ced750e3"}, + {file = "rpds_py-0.13.2-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:4dcc5ee1d0275cb78d443fdebd0241e58772a354a6d518b1d7af1580bbd2c4e8"}, + {file = "rpds_py-0.13.2-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:61d42d2b08430854485135504f672c14d4fc644dd243a9c17e7c4e0faf5ed07e"}, + {file = "rpds_py-0.13.2-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d3a61e928feddc458a55110f42f626a2a20bea942ccedb6fb4cee70b4830ed41"}, + {file = "rpds_py-0.13.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7de12b69d95072394998c622cfd7e8cea8f560db5fca6a62a148f902a1029f8b"}, + {file = "rpds_py-0.13.2-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:87a90f5545fd61f6964e65eebde4dc3fa8660bb7d87adb01d4cf17e0a2b484ad"}, + {file = "rpds_py-0.13.2-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:9c95a1a290f9acf7a8f2ebbdd183e99215d491beea52d61aa2a7a7d2c618ddc6"}, + {file = "rpds_py-0.13.2-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:35f53c76a712e323c779ca39b9a81b13f219a8e3bc15f106ed1e1462d56fcfe9"}, + {file = "rpds_py-0.13.2-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:96fb0899bb2ab353f42e5374c8f0789f54e0a94ef2f02b9ac7149c56622eaf31"}, + {file = "rpds_py-0.13.2.tar.gz", hash = "sha256:f8eae66a1304de7368932b42d801c67969fd090ddb1a7a24f27b435ed4bed68f"}, ] [[package]] name = "rtfde" -version = "0.1.0" +version = "0.1.1" description = "A library for extracting HTML content from RTF encapsulated HTML as commonly found in the exchange MSG email format." optional = true -python-versions = ">=3.6" +python-versions = ">=3.8" files = [ - {file = "RTFDE-0.1.0-py3-none-any.whl", hash = "sha256:a110dbef435803f3fba717d51a7b9c7a92695c2461637cc6eaf36a9f54386e26"}, - {file = "RTFDE-0.1.0.tar.gz", hash = "sha256:12215ee59856208010b9200c19afe0f9fa13a3fb39f44015979299c248cbacd7"}, + {file = "RTFDE-0.1.1-py3-none-any.whl", hash = "sha256:ea7ab0e0b9d4af08415f5017ecff91d74e24216a5e4e4682155cedc478035e99"}, + {file = "RTFDE-0.1.1.tar.gz", hash = "sha256:9e43485e79b2dd1018127735d8134f65d2a9d73af314d2a101f10346333b241e"}, ] [package.dependencies] -lark = "1.1.5" +lark = "1.1.8" oletools = ">=0.56" [package.extras] @@ -3366,13 +3367,13 @@ files = [ [[package]] name = "websocket-client" -version = "1.6.4" +version = "1.7.0" description = "WebSocket client for Python with low level API options" optional = false python-versions = ">=3.8" files = [ - {file = "websocket-client-1.6.4.tar.gz", hash = "sha256:b3324019b3c28572086c4a319f91d1dcd44e6e11cd340232978c684a7650d0df"}, - {file = "websocket_client-1.6.4-py3-none-any.whl", hash = "sha256:084072e0a7f5f347ef2ac3d8698a5e0b4ffbfcab607628cadabc650fc9a83a24"}, + {file = "websocket-client-1.7.0.tar.gz", hash = "sha256:10e511ea3a8c744631d3bd77e61eb17ed09304c413ad42cf6ddfa4c7787e8fe6"}, + {file = "websocket_client-1.7.0-py3-none-any.whl", hash = "sha256:f4c3d22fec12a2461427a29957ff07d35098ee2d976d3ba244e688b8b4057588"}, ] [package.extras] @@ -3497,4 +3498,4 @@ virustotal = ["validators"] [metadata] lock-version = "2.0" python-versions = "^3.8" -content-hash = "69b4eb7ce67629e2b3f4f085fa17cea8e9faf1b638c9807ae175ec00b1ebca8e" +content-hash = "0936745ef035e04cf066043004f4a4bb522bcd77b1b6b342796cf5ac2442d71b" diff --git a/pyproject.toml b/pyproject.toml index a692098..bcb2ad6 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -46,7 +46,7 @@ python-dateutil = "^2.8.2" jsonschema = ">=4.17.3" deprecated = "^1.2.14" extract_msg = {version = "^0.46.2", optional = true} -RTFDE = {version = "^0.1.0", optional = true} +RTFDE = {version = "^0.1.1", optional = true} oletools = {version = "^0.60.1", optional = true} python-magic = {version = "^0.4.27", optional = true} pydeep2 = {version = "^0.5.1", optional = true} From 2c6e1e6ea106f4312dcd2f35357afada94d32c52 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 6 Dec 2023 16:10:15 +0000 Subject: [PATCH 10/80] build(deps): bump actions/setup-python from 4 to 5 Bumps [actions/setup-python](https://github.com/actions/setup-python) from 4 to 5. - [Release notes](https://github.com/actions/setup-python/releases) - [Commits](https://github.com/actions/setup-python/compare/v4...v5) --- updated-dependencies: - dependency-name: actions/setup-python dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/pytest.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pytest.yml b/.github/workflows/pytest.yml index cd699ba..08ff3e7 100644 --- a/.github/workflows/pytest.yml +++ b/.github/workflows/pytest.yml @@ -22,7 +22,7 @@ jobs: submodules: recursive - name: Set up Python ${{matrix.python-version}} - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: ${{matrix.python-version}} From d5bab9ca8d24de236413a47c53ce9d50cbc1f474 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Vinot?= Date: Tue, 12 Dec 2023 00:57:15 +0100 Subject: [PATCH 11/80] chg: Bump deps --- poetry.lock | 262 ++++++++++++++++++++++++++----------------------- pyproject.toml | 8 +- 2 files changed, 143 insertions(+), 127 deletions(-) diff --git a/poetry.lock b/poetry.lock index 1181c8f..d0d286c 100644 --- a/poetry.lock +++ b/poetry.lock @@ -468,6 +468,17 @@ files = [ [package.dependencies] pycparser = "*" +[[package]] +name = "chardet" +version = "5.2.0" +description = "Universal encoding detector for Python 3" +optional = true +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" @@ -870,22 +881,22 @@ tests = ["asttokens (>=2.1.0)", "coverage", "coverage-enable-subprocess", "ipyth [[package]] name = "extract-msg" -version = "0.46.2" +version = "0.47.0" description = "Extracts emails and attachments saved in Microsoft Outlook's .msg files" optional = true python-versions = ">=3.8" files = [ - {file = "extract_msg-0.46.2-py2.py3-none-any.whl", hash = "sha256:f49e530d16ac3e89c1d954d03b9bf03e2703a86fdd640fc3c56f1b41024c74f6"}, - {file = "extract_msg-0.46.2.tar.gz", hash = "sha256:1ccc852881bba973a1f2e2b65e72138aaf2b5784dddc13be34d65af1c410e8ab"}, + {file = "extract_msg-0.47.0-py2.py3-none-any.whl", hash = "sha256:ab177546d6ebbea7818e9acb352f6f8cce3821e39319405e6a873808238564a5"}, + {file = "extract_msg-0.47.0.tar.gz", hash = "sha256:d3ed5fdc8cdff3567421d7e4183511905eb3c83d2605e6c9335c653efa6cfb41"}, ] [package.dependencies] beautifulsoup4 = ">=4.11.1,<4.13" compressed-rtf = ">=1.0.6,<2" ebcdic = ">=1.1.1,<2" -olefile = "0.46" +olefile = "0.47" red-black-tree-mod = "1.20" -RTFDE = ">=0.1.0,<0.2" +RTFDE = ">=0.1.1,<0.2" tzlocal = ">=4.2,<6" [package.extras] @@ -1304,13 +1315,13 @@ jupyter-server = ">=1.1.2" [[package]] name = "jupyter-server" -version = "2.11.2" +version = "2.12.1" description = "The backend—i.e. core services, APIs, and REST endpoints—to Jupyter web applications." optional = false python-versions = ">=3.8" files = [ - {file = "jupyter_server-2.11.2-py3-none-any.whl", hash = "sha256:0c548151b54bcb516ca466ec628f7f021545be137d01b5467877e87f6fff4374"}, - {file = "jupyter_server-2.11.2.tar.gz", hash = "sha256:0c99f9367b0f24141e527544522430176613f9249849be80504c6d2b955004bb"}, + {file = "jupyter_server-2.12.1-py3-none-any.whl", hash = "sha256:fd030dd7be1ca572e4598203f718df6630c12bd28a599d7f1791c4d7938e1010"}, + {file = "jupyter_server-2.12.1.tar.gz", hash = "sha256:dc77b7dcc5fc0547acba2b2844f01798008667201eea27c6319ff9257d700a6d"}, ] [package.dependencies] @@ -1340,13 +1351,13 @@ test = ["flaky", "ipykernel", "pre-commit", "pytest (>=7.0)", "pytest-console-sc [[package]] name = "jupyter-server-terminals" -version = "0.4.4" +version = "0.5.0" description = "A Jupyter Server Extension Providing Terminals." optional = false python-versions = ">=3.8" files = [ - {file = "jupyter_server_terminals-0.4.4-py3-none-any.whl", hash = "sha256:75779164661cec02a8758a5311e18bb8eb70c4e86c6b699403100f1585a12a36"}, - {file = "jupyter_server_terminals-0.4.4.tar.gz", hash = "sha256:57ab779797c25a7ba68e97bcfb5d7740f2b5e8a83b5e8102b10438041a7eac5d"}, + {file = "jupyter_server_terminals-0.5.0-py3-none-any.whl", hash = "sha256:2fc0692c883bfd891f4fba0c4b4a684a37234b0ba472f2e97ed0a3888f46e1e4"}, + {file = "jupyter_server_terminals-0.5.0.tar.gz", hash = "sha256:ebcd68c9afbf98a480a533e6f3266354336e645536953b7abcc7bdeebc0154a3"}, ] [package.dependencies] @@ -1354,8 +1365,8 @@ pywinpty = {version = ">=2.0.3", markers = "os_name == \"nt\""} terminado = ">=0.8.3" [package.extras] -docs = ["jinja2", "jupyter-server", "mistune (<3.0)", "myst-parser", "nbformat", "packaging", "pydata-sphinx-theme", "sphinxcontrib-github-alt", "sphinxcontrib-openapi", "sphinxcontrib-spelling", "sphinxemoji", "tornado"] -test = ["coverage", "jupyter-server (>=2.0.0)", "pytest (>=7.0)", "pytest-cov", "pytest-jupyter[server] (>=0.5.3)", "pytest-timeout"] +docs = ["jinja2", "jupyter-server", "mistune (<4.0)", "myst-parser", "nbformat", "packaging", "pydata-sphinx-theme", "sphinxcontrib-github-alt", "sphinxcontrib-openapi", "sphinxcontrib-spelling", "sphinxemoji", "tornado"] +test = ["jupyter-server (>=2.0.0)", "pytest (>=7.0)", "pytest-jupyter[server] (>=0.5.3)", "pytest-timeout"] [[package]] name = "jupyterlab" @@ -1744,14 +1755,18 @@ test = ["pytest", "pytest-console-scripts", "pytest-jupyter", "pytest-tornasync" [[package]] name = "olefile" -version = "0.46" +version = "0.47" description = "Python package to parse, read and write Microsoft OLE2 files (Structured Storage or Compound Document, Microsoft Office)" optional = true -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" files = [ - {file = "olefile-0.46.zip", hash = "sha256:133b031eaf8fd2c9399b78b8bc5b8fcbe4c31e85295749bb17a87cba8f3c3964"}, + {file = "olefile-0.47-py2.py3-none-any.whl", hash = "sha256:543c7da2a7adadf21214938bb79c83ea12b473a4b6ee4ad4bf854e7715e13d1f"}, + {file = "olefile-0.47.zip", hash = "sha256:599383381a0bf3dfbd932ca0ca6515acd174ed48870cbf7fee123d698c192c1c"}, ] +[package.extras] +tests = ["pytest", "pytest-cov"] + [[package]] name = "oletools" version = "0.60.1" @@ -2039,13 +2054,13 @@ files = [ [[package]] name = "publicsuffixlist" -version = "0.10.0.20231122" +version = "0.10.0.20231207" description = "publicsuffixlist implement" optional = true python-versions = ">=2.6" files = [ - {file = "publicsuffixlist-0.10.0.20231122-py2.py3-none-any.whl", hash = "sha256:ce47acf7fb7e817fba8397b43896fcb4b4307d41e2c9d2f63418b3e65c7f15cb"}, - {file = "publicsuffixlist-0.10.0.20231122.tar.gz", hash = "sha256:d02ac754fa104d2dc8f593ef7ffe305905f8bd89f9bc079653135a9e39db17ad"}, + {file = "publicsuffixlist-0.10.0.20231207-py2.py3-none-any.whl", hash = "sha256:b23f00837f898d13311f5c648759acb4c2f4dc20fe6028839a4e1a60bac5ff7d"}, + {file = "publicsuffixlist-0.10.0.20231207.tar.gz", hash = "sha256:fea76083417296f62b2e5204ab35c5c1ac615c23f50c2865056bc9420653ade3"}, ] [package.extras] @@ -2312,104 +2327,104 @@ files = [ [[package]] name = "pyzmq" -version = "25.1.1" +version = "25.1.2" description = "Python bindings for 0MQ" optional = false python-versions = ">=3.6" files = [ - {file = "pyzmq-25.1.1-cp310-cp310-macosx_10_15_universal2.whl", hash = "sha256:381469297409c5adf9a0e884c5eb5186ed33137badcbbb0560b86e910a2f1e76"}, - {file = "pyzmq-25.1.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:955215ed0604dac5b01907424dfa28b40f2b2292d6493445dd34d0dfa72586a8"}, - {file = "pyzmq-25.1.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:985bbb1316192b98f32e25e7b9958088431d853ac63aca1d2c236f40afb17c83"}, - {file = "pyzmq-25.1.1-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:afea96f64efa98df4da6958bae37f1cbea7932c35878b185e5982821bc883369"}, - {file = "pyzmq-25.1.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:76705c9325d72a81155bb6ab48d4312e0032bf045fb0754889133200f7a0d849"}, - {file = "pyzmq-25.1.1-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:77a41c26205d2353a4c94d02be51d6cbdf63c06fbc1295ea57dad7e2d3381b71"}, - {file = "pyzmq-25.1.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:12720a53e61c3b99d87262294e2b375c915fea93c31fc2336898c26d7aed34cd"}, - {file = "pyzmq-25.1.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:57459b68e5cd85b0be8184382cefd91959cafe79ae019e6b1ae6e2ba8a12cda7"}, - {file = "pyzmq-25.1.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:292fe3fc5ad4a75bc8df0dfaee7d0babe8b1f4ceb596437213821f761b4589f9"}, - {file = "pyzmq-25.1.1-cp310-cp310-win32.whl", hash = "sha256:35b5ab8c28978fbbb86ea54958cd89f5176ce747c1fb3d87356cf698048a7790"}, - {file = "pyzmq-25.1.1-cp310-cp310-win_amd64.whl", hash = "sha256:11baebdd5fc5b475d484195e49bae2dc64b94a5208f7c89954e9e354fc609d8f"}, - {file = "pyzmq-25.1.1-cp311-cp311-macosx_10_15_universal2.whl", hash = "sha256:d20a0ddb3e989e8807d83225a27e5c2eb2260eaa851532086e9e0fa0d5287d83"}, - {file = "pyzmq-25.1.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:e1c1be77bc5fb77d923850f82e55a928f8638f64a61f00ff18a67c7404faf008"}, - {file = "pyzmq-25.1.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d89528b4943d27029a2818f847c10c2cecc79fa9590f3cb1860459a5be7933eb"}, - {file = "pyzmq-25.1.1-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:90f26dc6d5f241ba358bef79be9ce06de58d477ca8485e3291675436d3827cf8"}, - {file = "pyzmq-25.1.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c2b92812bd214018e50b6380ea3ac0c8bb01ac07fcc14c5f86a5bb25e74026e9"}, - {file = "pyzmq-25.1.1-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:2f957ce63d13c28730f7fd6b72333814221c84ca2421298f66e5143f81c9f91f"}, - {file = "pyzmq-25.1.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:047a640f5c9c6ade7b1cc6680a0e28c9dd5a0825135acbd3569cc96ea00b2505"}, - {file = "pyzmq-25.1.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:7f7e58effd14b641c5e4dec8c7dab02fb67a13df90329e61c869b9cc607ef752"}, - {file = "pyzmq-25.1.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:c2910967e6ab16bf6fbeb1f771c89a7050947221ae12a5b0b60f3bca2ee19bca"}, - {file = "pyzmq-25.1.1-cp311-cp311-win32.whl", hash = "sha256:76c1c8efb3ca3a1818b837aea423ff8a07bbf7aafe9f2f6582b61a0458b1a329"}, - {file = "pyzmq-25.1.1-cp311-cp311-win_amd64.whl", hash = "sha256:44e58a0554b21fc662f2712814a746635ed668d0fbc98b7cb9d74cb798d202e6"}, - {file = "pyzmq-25.1.1-cp312-cp312-macosx_10_15_universal2.whl", hash = "sha256:e1ffa1c924e8c72778b9ccd386a7067cddf626884fd8277f503c48bb5f51c762"}, - {file = "pyzmq-25.1.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:1af379b33ef33757224da93e9da62e6471cf4a66d10078cf32bae8127d3d0d4a"}, - {file = "pyzmq-25.1.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cff084c6933680d1f8b2f3b4ff5bbb88538a4aac00d199ac13f49d0698727ecb"}, - {file = "pyzmq-25.1.1-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e2400a94f7dd9cb20cd012951a0cbf8249e3d554c63a9c0cdfd5cbb6c01d2dec"}, - {file = "pyzmq-25.1.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2d81f1ddae3858b8299d1da72dd7d19dd36aab654c19671aa8a7e7fb02f6638a"}, - {file = "pyzmq-25.1.1-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:255ca2b219f9e5a3a9ef3081512e1358bd4760ce77828e1028b818ff5610b87b"}, - {file = "pyzmq-25.1.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:a882ac0a351288dd18ecae3326b8a49d10c61a68b01419f3a0b9a306190baf69"}, - {file = "pyzmq-25.1.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:724c292bb26365659fc434e9567b3f1adbdb5e8d640c936ed901f49e03e5d32e"}, - {file = "pyzmq-25.1.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4ca1ed0bb2d850aa8471387882247c68f1e62a4af0ce9c8a1dbe0d2bf69e41fb"}, - {file = "pyzmq-25.1.1-cp312-cp312-win32.whl", hash = "sha256:b3451108ab861040754fa5208bca4a5496c65875710f76789a9ad27c801a0075"}, - {file = "pyzmq-25.1.1-cp312-cp312-win_amd64.whl", hash = "sha256:eadbefd5e92ef8a345f0525b5cfd01cf4e4cc651a2cffb8f23c0dd184975d787"}, - {file = "pyzmq-25.1.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:db0b2af416ba735c6304c47f75d348f498b92952f5e3e8bff449336d2728795d"}, - {file = "pyzmq-25.1.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c7c133e93b405eb0d36fa430c94185bdd13c36204a8635470cccc200723c13bb"}, - {file = "pyzmq-25.1.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:273bc3959bcbff3f48606b28229b4721716598d76b5aaea2b4a9d0ab454ec062"}, - {file = "pyzmq-25.1.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:cbc8df5c6a88ba5ae385d8930da02201165408dde8d8322072e3e5ddd4f68e22"}, - {file = "pyzmq-25.1.1-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:18d43df3f2302d836f2a56f17e5663e398416e9dd74b205b179065e61f1a6edf"}, - {file = "pyzmq-25.1.1-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:73461eed88a88c866656e08f89299720a38cb4e9d34ae6bf5df6f71102570f2e"}, - {file = "pyzmq-25.1.1-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:34c850ce7976d19ebe7b9d4b9bb8c9dfc7aac336c0958e2651b88cbd46682123"}, - {file = "pyzmq-25.1.1-cp36-cp36m-win32.whl", hash = "sha256:d2045d6d9439a0078f2a34b57c7b18c4a6aef0bee37f22e4ec9f32456c852c71"}, - {file = "pyzmq-25.1.1-cp36-cp36m-win_amd64.whl", hash = "sha256:458dea649f2f02a0b244ae6aef8dc29325a2810aa26b07af8374dc2a9faf57e3"}, - {file = "pyzmq-25.1.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:7cff25c5b315e63b07a36f0c2bab32c58eafbe57d0dce61b614ef4c76058c115"}, - {file = "pyzmq-25.1.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b1579413ae492b05de5a6174574f8c44c2b9b122a42015c5292afa4be2507f28"}, - {file = "pyzmq-25.1.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:3d0a409d3b28607cc427aa5c30a6f1e4452cc44e311f843e05edb28ab5e36da0"}, - {file = "pyzmq-25.1.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:21eb4e609a154a57c520e3d5bfa0d97e49b6872ea057b7c85257b11e78068222"}, - {file = "pyzmq-25.1.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:034239843541ef7a1aee0c7b2cb7f6aafffb005ede965ae9cbd49d5ff4ff73cf"}, - {file = "pyzmq-25.1.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:f8115e303280ba09f3898194791a153862cbf9eef722ad8f7f741987ee2a97c7"}, - {file = "pyzmq-25.1.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:1a5d26fe8f32f137e784f768143728438877d69a586ddeaad898558dc971a5ae"}, - {file = "pyzmq-25.1.1-cp37-cp37m-win32.whl", hash = "sha256:f32260e556a983bc5c7ed588d04c942c9a8f9c2e99213fec11a031e316874c7e"}, - {file = "pyzmq-25.1.1-cp37-cp37m-win_amd64.whl", hash = "sha256:abf34e43c531bbb510ae7e8f5b2b1f2a8ab93219510e2b287a944432fad135f3"}, - {file = "pyzmq-25.1.1-cp38-cp38-macosx_10_15_universal2.whl", hash = "sha256:87e34f31ca8f168c56d6fbf99692cc8d3b445abb5bfd08c229ae992d7547a92a"}, - {file = "pyzmq-25.1.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:c9c6c9b2c2f80747a98f34ef491c4d7b1a8d4853937bb1492774992a120f475d"}, - {file = "pyzmq-25.1.1-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:5619f3f5a4db5dbb572b095ea3cb5cc035335159d9da950830c9c4db2fbb6995"}, - {file = "pyzmq-25.1.1-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:5a34d2395073ef862b4032343cf0c32a712f3ab49d7ec4f42c9661e0294d106f"}, - {file = "pyzmq-25.1.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:25f0e6b78220aba09815cd1f3a32b9c7cb3e02cb846d1cfc526b6595f6046618"}, - {file = "pyzmq-25.1.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:3669cf8ee3520c2f13b2e0351c41fea919852b220988d2049249db10046a7afb"}, - {file = "pyzmq-25.1.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:2d163a18819277e49911f7461567bda923461c50b19d169a062536fffe7cd9d2"}, - {file = "pyzmq-25.1.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:df27ffddff4190667d40de7beba4a950b5ce78fe28a7dcc41d6f8a700a80a3c0"}, - {file = "pyzmq-25.1.1-cp38-cp38-win32.whl", hash = "sha256:a382372898a07479bd34bda781008e4a954ed8750f17891e794521c3e21c2e1c"}, - {file = "pyzmq-25.1.1-cp38-cp38-win_amd64.whl", hash = "sha256:52533489f28d62eb1258a965f2aba28a82aa747202c8fa5a1c7a43b5db0e85c1"}, - {file = "pyzmq-25.1.1-cp39-cp39-macosx_10_15_universal2.whl", hash = "sha256:03b3f49b57264909aacd0741892f2aecf2f51fb053e7d8ac6767f6c700832f45"}, - {file = "pyzmq-25.1.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:330f9e188d0d89080cde66dc7470f57d1926ff2fb5576227f14d5be7ab30b9fa"}, - {file = "pyzmq-25.1.1-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:2ca57a5be0389f2a65e6d3bb2962a971688cbdd30b4c0bd188c99e39c234f414"}, - {file = "pyzmq-25.1.1-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:d457aed310f2670f59cc5b57dcfced452aeeed77f9da2b9763616bd57e4dbaae"}, - {file = "pyzmq-25.1.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c56d748ea50215abef7030c72b60dd723ed5b5c7e65e7bc2504e77843631c1a6"}, - {file = "pyzmq-25.1.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:8f03d3f0d01cb5a018debeb412441996a517b11c5c17ab2001aa0597c6d6882c"}, - {file = "pyzmq-25.1.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:820c4a08195a681252f46926de10e29b6bbf3e17b30037bd4250d72dd3ddaab8"}, - {file = "pyzmq-25.1.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:17ef5f01d25b67ca8f98120d5fa1d21efe9611604e8eb03a5147360f517dd1e2"}, - {file = "pyzmq-25.1.1-cp39-cp39-win32.whl", hash = "sha256:04ccbed567171579ec2cebb9c8a3e30801723c575601f9a990ab25bcac6b51e2"}, - {file = "pyzmq-25.1.1-cp39-cp39-win_amd64.whl", hash = "sha256:e61f091c3ba0c3578411ef505992d356a812fb200643eab27f4f70eed34a29ef"}, - {file = "pyzmq-25.1.1-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:ade6d25bb29c4555d718ac6d1443a7386595528c33d6b133b258f65f963bb0f6"}, - {file = "pyzmq-25.1.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e0c95ddd4f6e9fca4e9e3afaa4f9df8552f0ba5d1004e89ef0a68e1f1f9807c7"}, - {file = "pyzmq-25.1.1-pp310-pypy310_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:48e466162a24daf86f6b5ca72444d2bf39a5e58da5f96370078be67c67adc978"}, - {file = "pyzmq-25.1.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:abc719161780932c4e11aaebb203be3d6acc6b38d2f26c0f523b5b59d2fc1996"}, - {file = "pyzmq-25.1.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:1ccf825981640b8c34ae54231b7ed00271822ea1c6d8ba1090ebd4943759abf5"}, - {file = "pyzmq-25.1.1-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:c2f20ce161ebdb0091a10c9ca0372e023ce24980d0e1f810f519da6f79c60800"}, - {file = "pyzmq-25.1.1-pp37-pypy37_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:deee9ca4727f53464daf089536e68b13e6104e84a37820a88b0a057b97bba2d2"}, - {file = "pyzmq-25.1.1-pp37-pypy37_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:aa8d6cdc8b8aa19ceb319aaa2b660cdaccc533ec477eeb1309e2a291eaacc43a"}, - {file = "pyzmq-25.1.1-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:019e59ef5c5256a2c7378f2fb8560fc2a9ff1d315755204295b2eab96b254d0a"}, - {file = "pyzmq-25.1.1-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:b9af3757495c1ee3b5c4e945c1df7be95562277c6e5bccc20a39aec50f826cd0"}, - {file = "pyzmq-25.1.1-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:548d6482dc8aadbe7e79d1b5806585c8120bafa1ef841167bc9090522b610fa6"}, - {file = "pyzmq-25.1.1-pp38-pypy38_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:057e824b2aae50accc0f9a0570998adc021b372478a921506fddd6c02e60308e"}, - {file = "pyzmq-25.1.1-pp38-pypy38_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:2243700cc5548cff20963f0ca92d3e5e436394375ab8a354bbea2b12911b20b0"}, - {file = "pyzmq-25.1.1-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:79986f3b4af059777111409ee517da24a529bdbd46da578b33f25580adcff728"}, - {file = "pyzmq-25.1.1-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:11d58723d44d6ed4dd677c5615b2ffb19d5c426636345567d6af82be4dff8a55"}, - {file = "pyzmq-25.1.1-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:49d238cf4b69652257db66d0c623cd3e09b5d2e9576b56bc067a396133a00d4a"}, - {file = "pyzmq-25.1.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fedbdc753827cf014c01dbbee9c3be17e5a208dcd1bf8641ce2cd29580d1f0d4"}, - {file = "pyzmq-25.1.1-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bc16ac425cc927d0a57d242589f87ee093884ea4804c05a13834d07c20db203c"}, - {file = "pyzmq-25.1.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:11c1d2aed9079c6b0c9550a7257a836b4a637feb334904610f06d70eb44c56d2"}, - {file = "pyzmq-25.1.1-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:e8a701123029cc240cea61dd2d16ad57cab4691804143ce80ecd9286b464d180"}, - {file = "pyzmq-25.1.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:61706a6b6c24bdece85ff177fec393545a3191eeda35b07aaa1458a027ad1304"}, - {file = "pyzmq-25.1.1.tar.gz", hash = "sha256:259c22485b71abacdfa8bf79720cd7bcf4b9d128b30ea554f01ae71fdbfdaa23"}, + {file = "pyzmq-25.1.2-cp310-cp310-macosx_10_15_universal2.whl", hash = "sha256:e624c789359f1a16f83f35e2c705d07663ff2b4d4479bad35621178d8f0f6ea4"}, + {file = "pyzmq-25.1.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:49151b0efece79f6a79d41a461d78535356136ee70084a1c22532fc6383f4ad0"}, + {file = "pyzmq-25.1.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d9a5f194cf730f2b24d6af1f833c14c10f41023da46a7f736f48b6d35061e76e"}, + {file = "pyzmq-25.1.2-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:faf79a302f834d9e8304fafdc11d0d042266667ac45209afa57e5efc998e3872"}, + {file = "pyzmq-25.1.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f51a7b4ead28d3fca8dda53216314a553b0f7a91ee8fc46a72b402a78c3e43d"}, + {file = "pyzmq-25.1.2-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:0ddd6d71d4ef17ba5a87becf7ddf01b371eaba553c603477679ae817a8d84d75"}, + {file = "pyzmq-25.1.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:246747b88917e4867e2367b005fc8eefbb4a54b7db363d6c92f89d69abfff4b6"}, + {file = "pyzmq-25.1.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:00c48ae2fd81e2a50c3485de1b9d5c7c57cd85dc8ec55683eac16846e57ac979"}, + {file = "pyzmq-25.1.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:5a68d491fc20762b630e5db2191dd07ff89834086740f70e978bb2ef2668be08"}, + {file = "pyzmq-25.1.2-cp310-cp310-win32.whl", hash = "sha256:09dfe949e83087da88c4a76767df04b22304a682d6154de2c572625c62ad6886"}, + {file = "pyzmq-25.1.2-cp310-cp310-win_amd64.whl", hash = "sha256:fa99973d2ed20417744fca0073390ad65ce225b546febb0580358e36aa90dba6"}, + {file = "pyzmq-25.1.2-cp311-cp311-macosx_10_15_universal2.whl", hash = "sha256:82544e0e2d0c1811482d37eef297020a040c32e0687c1f6fc23a75b75db8062c"}, + {file = "pyzmq-25.1.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:01171fc48542348cd1a360a4b6c3e7d8f46cdcf53a8d40f84db6707a6768acc1"}, + {file = "pyzmq-25.1.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bc69c96735ab501419c432110016329bf0dea8898ce16fab97c6d9106dc0b348"}, + {file = "pyzmq-25.1.2-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3e124e6b1dd3dfbeb695435dff0e383256655bb18082e094a8dd1f6293114642"}, + {file = "pyzmq-25.1.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7598d2ba821caa37a0f9d54c25164a4fa351ce019d64d0b44b45540950458840"}, + {file = "pyzmq-25.1.2-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:d1299d7e964c13607efd148ca1f07dcbf27c3ab9e125d1d0ae1d580a1682399d"}, + {file = "pyzmq-25.1.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:4e6f689880d5ad87918430957297c975203a082d9a036cc426648fcbedae769b"}, + {file = "pyzmq-25.1.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:cc69949484171cc961e6ecd4a8911b9ce7a0d1f738fcae717177c231bf77437b"}, + {file = "pyzmq-25.1.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:9880078f683466b7f567b8624bfc16cad65077be046b6e8abb53bed4eeb82dd3"}, + {file = "pyzmq-25.1.2-cp311-cp311-win32.whl", hash = "sha256:4e5837af3e5aaa99a091302df5ee001149baff06ad22b722d34e30df5f0d9097"}, + {file = "pyzmq-25.1.2-cp311-cp311-win_amd64.whl", hash = "sha256:25c2dbb97d38b5ac9fd15586e048ec5eb1e38f3d47fe7d92167b0c77bb3584e9"}, + {file = "pyzmq-25.1.2-cp312-cp312-macosx_10_15_universal2.whl", hash = "sha256:11e70516688190e9c2db14fcf93c04192b02d457b582a1f6190b154691b4c93a"}, + {file = "pyzmq-25.1.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:313c3794d650d1fccaaab2df942af9f2c01d6217c846177cfcbc693c7410839e"}, + {file = "pyzmq-25.1.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1b3cbba2f47062b85fe0ef9de5b987612140a9ba3a9c6d2543c6dec9f7c2ab27"}, + {file = "pyzmq-25.1.2-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fc31baa0c32a2ca660784d5af3b9487e13b61b3032cb01a115fce6588e1bed30"}, + {file = "pyzmq-25.1.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:02c9087b109070c5ab0b383079fa1b5f797f8d43e9a66c07a4b8b8bdecfd88ee"}, + {file = "pyzmq-25.1.2-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:f8429b17cbb746c3e043cb986328da023657e79d5ed258b711c06a70c2ea7537"}, + {file = "pyzmq-25.1.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:5074adeacede5f810b7ef39607ee59d94e948b4fd954495bdb072f8c54558181"}, + {file = "pyzmq-25.1.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:7ae8f354b895cbd85212da245f1a5ad8159e7840e37d78b476bb4f4c3f32a9fe"}, + {file = "pyzmq-25.1.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:b264bf2cc96b5bc43ce0e852be995e400376bd87ceb363822e2cb1964fcdc737"}, + {file = "pyzmq-25.1.2-cp312-cp312-win32.whl", hash = "sha256:02bbc1a87b76e04fd780b45e7f695471ae6de747769e540da909173d50ff8e2d"}, + {file = "pyzmq-25.1.2-cp312-cp312-win_amd64.whl", hash = "sha256:ced111c2e81506abd1dc142e6cd7b68dd53747b3b7ae5edbea4578c5eeff96b7"}, + {file = "pyzmq-25.1.2-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:7b6d09a8962a91151f0976008eb7b29b433a560fde056ec7a3db9ec8f1075438"}, + {file = "pyzmq-25.1.2-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:967668420f36878a3c9ecb5ab33c9d0ff8d054f9c0233d995a6d25b0e95e1b6b"}, + {file = "pyzmq-25.1.2-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5edac3f57c7ddaacdb4d40f6ef2f9e299471fc38d112f4bc6d60ab9365445fb0"}, + {file = "pyzmq-25.1.2-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:0dabfb10ef897f3b7e101cacba1437bd3a5032ee667b7ead32bbcdd1a8422fe7"}, + {file = "pyzmq-25.1.2-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:2c6441e0398c2baacfe5ba30c937d274cfc2dc5b55e82e3749e333aabffde561"}, + {file = "pyzmq-25.1.2-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:16b726c1f6c2e7625706549f9dbe9b06004dfbec30dbed4bf50cbdfc73e5b32a"}, + {file = "pyzmq-25.1.2-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:a86c2dd76ef71a773e70551a07318b8e52379f58dafa7ae1e0a4be78efd1ff16"}, + {file = "pyzmq-25.1.2-cp36-cp36m-win32.whl", hash = "sha256:359f7f74b5d3c65dae137f33eb2bcfa7ad9ebefd1cab85c935f063f1dbb245cc"}, + {file = "pyzmq-25.1.2-cp36-cp36m-win_amd64.whl", hash = "sha256:55875492f820d0eb3417b51d96fea549cde77893ae3790fd25491c5754ea2f68"}, + {file = "pyzmq-25.1.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b8c8a419dfb02e91b453615c69568442e897aaf77561ee0064d789705ff37a92"}, + {file = "pyzmq-25.1.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8807c87fa893527ae8a524c15fc505d9950d5e856f03dae5921b5e9aa3b8783b"}, + {file = "pyzmq-25.1.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5e319ed7d6b8f5fad9b76daa0a68497bc6f129858ad956331a5835785761e003"}, + {file = "pyzmq-25.1.2-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:3c53687dde4d9d473c587ae80cc328e5b102b517447456184b485587ebd18b62"}, + {file = "pyzmq-25.1.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:9add2e5b33d2cd765ad96d5eb734a5e795a0755f7fc49aa04f76d7ddda73fd70"}, + {file = "pyzmq-25.1.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:e690145a8c0c273c28d3b89d6fb32c45e0d9605b2293c10e650265bf5c11cfec"}, + {file = "pyzmq-25.1.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:00a06faa7165634f0cac1abb27e54d7a0b3b44eb9994530b8ec73cf52e15353b"}, + {file = "pyzmq-25.1.2-cp37-cp37m-win32.whl", hash = "sha256:0f97bc2f1f13cb16905a5f3e1fbdf100e712d841482b2237484360f8bc4cb3d7"}, + {file = "pyzmq-25.1.2-cp37-cp37m-win_amd64.whl", hash = "sha256:6cc0020b74b2e410287e5942e1e10886ff81ac77789eb20bec13f7ae681f0fdd"}, + {file = "pyzmq-25.1.2-cp38-cp38-macosx_10_15_universal2.whl", hash = "sha256:bef02cfcbded83473bdd86dd8d3729cd82b2e569b75844fb4ea08fee3c26ae41"}, + {file = "pyzmq-25.1.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:e10a4b5a4b1192d74853cc71a5e9fd022594573926c2a3a4802020360aa719d8"}, + {file = "pyzmq-25.1.2-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:8c5f80e578427d4695adac6fdf4370c14a2feafdc8cb35549c219b90652536ae"}, + {file = "pyzmq-25.1.2-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:5dde6751e857910c1339890f3524de74007958557593b9e7e8c5f01cd919f8a7"}, + {file = "pyzmq-25.1.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ea1608dd169da230a0ad602d5b1ebd39807ac96cae1845c3ceed39af08a5c6df"}, + {file = "pyzmq-25.1.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:0f513130c4c361201da9bc69df25a086487250e16b5571ead521b31ff6b02220"}, + {file = "pyzmq-25.1.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:019744b99da30330798bb37df33549d59d380c78e516e3bab9c9b84f87a9592f"}, + {file = "pyzmq-25.1.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:2e2713ef44be5d52dd8b8e2023d706bf66cb22072e97fc71b168e01d25192755"}, + {file = "pyzmq-25.1.2-cp38-cp38-win32.whl", hash = "sha256:07cd61a20a535524906595e09344505a9bd46f1da7a07e504b315d41cd42eb07"}, + {file = "pyzmq-25.1.2-cp38-cp38-win_amd64.whl", hash = "sha256:eb7e49a17fb8c77d3119d41a4523e432eb0c6932187c37deb6fbb00cc3028088"}, + {file = "pyzmq-25.1.2-cp39-cp39-macosx_10_15_universal2.whl", hash = "sha256:94504ff66f278ab4b7e03e4cba7e7e400cb73bfa9d3d71f58d8972a8dc67e7a6"}, + {file = "pyzmq-25.1.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6dd0d50bbf9dca1d0bdea219ae6b40f713a3fb477c06ca3714f208fd69e16fd8"}, + {file = "pyzmq-25.1.2-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:004ff469d21e86f0ef0369717351073e0e577428e514c47c8480770d5e24a565"}, + {file = "pyzmq-25.1.2-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:c0b5ca88a8928147b7b1e2dfa09f3b6c256bc1135a1338536cbc9ea13d3b7add"}, + {file = "pyzmq-25.1.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2c9a79f1d2495b167119d02be7448bfba57fad2a4207c4f68abc0bab4b92925b"}, + {file = "pyzmq-25.1.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:518efd91c3d8ac9f9b4f7dd0e2b7b8bf1a4fe82a308009016b07eaa48681af82"}, + {file = "pyzmq-25.1.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:1ec23bd7b3a893ae676d0e54ad47d18064e6c5ae1fadc2f195143fb27373f7f6"}, + {file = "pyzmq-25.1.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:db36c27baed588a5a8346b971477b718fdc66cf5b80cbfbd914b4d6d355e44e2"}, + {file = "pyzmq-25.1.2-cp39-cp39-win32.whl", hash = "sha256:39b1067f13aba39d794a24761e385e2eddc26295826530a8c7b6c6c341584289"}, + {file = "pyzmq-25.1.2-cp39-cp39-win_amd64.whl", hash = "sha256:8e9f3fabc445d0ce320ea2c59a75fe3ea591fdbdeebec5db6de530dd4b09412e"}, + {file = "pyzmq-25.1.2-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:a8c1d566344aee826b74e472e16edae0a02e2a044f14f7c24e123002dcff1c05"}, + {file = "pyzmq-25.1.2-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:759cfd391a0996345ba94b6a5110fca9c557ad4166d86a6e81ea526c376a01e8"}, + {file = "pyzmq-25.1.2-pp310-pypy310_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7c61e346ac34b74028ede1c6b4bcecf649d69b707b3ff9dc0fab453821b04d1e"}, + {file = "pyzmq-25.1.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4cb8fc1f8d69b411b8ec0b5f1ffbcaf14c1db95b6bccea21d83610987435f1a4"}, + {file = "pyzmq-25.1.2-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:3c00c9b7d1ca8165c610437ca0c92e7b5607b2f9076f4eb4b095c85d6e680a1d"}, + {file = "pyzmq-25.1.2-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:df0c7a16ebb94452d2909b9a7b3337940e9a87a824c4fc1c7c36bb4404cb0cde"}, + {file = "pyzmq-25.1.2-pp37-pypy37_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:45999e7f7ed5c390f2e87ece7f6c56bf979fb213550229e711e45ecc7d42ccb8"}, + {file = "pyzmq-25.1.2-pp37-pypy37_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:ac170e9e048b40c605358667aca3d94e98f604a18c44bdb4c102e67070f3ac9b"}, + {file = "pyzmq-25.1.2-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d1b604734bec94f05f81b360a272fc824334267426ae9905ff32dc2be433ab96"}, + {file = "pyzmq-25.1.2-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:a793ac733e3d895d96f865f1806f160696422554e46d30105807fdc9841b9f7d"}, + {file = "pyzmq-25.1.2-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:0806175f2ae5ad4b835ecd87f5f85583316b69f17e97786f7443baaf54b9bb98"}, + {file = "pyzmq-25.1.2-pp38-pypy38_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:ef12e259e7bc317c7597d4f6ef59b97b913e162d83b421dd0db3d6410f17a244"}, + {file = "pyzmq-25.1.2-pp38-pypy38_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:ea253b368eb41116011add00f8d5726762320b1bda892f744c91997b65754d73"}, + {file = "pyzmq-25.1.2-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1b9b1f2ad6498445a941d9a4fee096d387fee436e45cc660e72e768d3d8ee611"}, + {file = "pyzmq-25.1.2-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:8b14c75979ce932c53b79976a395cb2a8cd3aaf14aef75e8c2cb55a330b9b49d"}, + {file = "pyzmq-25.1.2-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:889370d5174a741a62566c003ee8ddba4b04c3f09a97b8000092b7ca83ec9c49"}, + {file = "pyzmq-25.1.2-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9a18fff090441a40ffda8a7f4f18f03dc56ae73f148f1832e109f9bffa85df15"}, + {file = "pyzmq-25.1.2-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:99a6b36f95c98839ad98f8c553d8507644c880cf1e0a57fe5e3a3f3969040882"}, + {file = "pyzmq-25.1.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4345c9a27f4310afbb9c01750e9461ff33d6fb74cd2456b107525bbeebcb5be3"}, + {file = "pyzmq-25.1.2-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:3516e0b6224cf6e43e341d56da15fd33bdc37fa0c06af4f029f7d7dfceceabbc"}, + {file = "pyzmq-25.1.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:146b9b1f29ead41255387fb07be56dc29639262c0f7344f570eecdcd8d683314"}, + {file = "pyzmq-25.1.2.tar.gz", hash = "sha256:93f1aa311e8bb912e34f004cf186407a4e90eec4f0ecc0efd26056bf7eda0226"}, ] [package.dependencies] @@ -2443,13 +2458,13 @@ files = [ [[package]] name = "referencing" -version = "0.31.1" +version = "0.32.0" description = "JSON Referencing + Python" optional = false python-versions = ">=3.8" files = [ - {file = "referencing-0.31.1-py3-none-any.whl", hash = "sha256:c19c4d006f1757e3dd75c4f784d38f8698d87b649c54f9ace14e5e8c9667c01d"}, - {file = "referencing-0.31.1.tar.gz", hash = "sha256:81a1471c68c9d5e3831c30ad1dd9815c45b558e596653db751a2bfdd17b3b9ec"}, + {file = "referencing-0.32.0-py3-none-any.whl", hash = "sha256:bdcd3efb936f82ff86f993093f6da7435c7de69a3b3a5a06678a6050184bee99"}, + {file = "referencing-0.32.0.tar.gz", hash = "sha256:689e64fe121843dcfd57b71933318ef1f91188ffb45367332700a86ac8fd6161"}, ] [package.dependencies] @@ -2458,16 +2473,17 @@ rpds-py = ">=0.7.0" [[package]] name = "reportlab" -version = "4.0.7" +version = "4.0.8" description = "The Reportlab Toolkit" optional = true python-versions = ">=3.7,<4" files = [ - {file = "reportlab-4.0.7-py3-none-any.whl", hash = "sha256:956d5874ee56e88753cf4c49452d6a7fa54a64e049a0382bd0c0b2013a26ef9a"}, - {file = "reportlab-4.0.7.tar.gz", hash = "sha256:967c77f00efd918cc231cf8b6d8f4e477dc973b5c16557e3bd18dfaeb5a70234"}, + {file = "reportlab-4.0.8-py3-none-any.whl", hash = "sha256:d00693de8ab8761b122e409de883ba976c24839f93867090c0d40b5d5906e847"}, + {file = "reportlab-4.0.8.tar.gz", hash = "sha256:169945817a1a7759fb7b7dae528c2f8064fc21d16338d9b572ebdcb756740853"}, ] [package.dependencies] +chardet = "*" pillow = ">=9.0.0" [package.extras] @@ -3234,13 +3250,13 @@ files = [ [[package]] name = "typing-extensions" -version = "4.8.0" +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.8.0-py3-none-any.whl", hash = "sha256:8f92fc8806f9a6b641eaa5318da32b44d401efaac0f6678c9bc448ba3605faa0"}, - {file = "typing_extensions-4.8.0.tar.gz", hash = "sha256:df8e4339e9cb77357558cbdbceca33c303714cf861d1eef15e1070055ae8b7ef"}, + {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]] @@ -3498,4 +3514,4 @@ virustotal = ["validators"] [metadata] lock-version = "2.0" python-versions = "^3.8" -content-hash = "0936745ef035e04cf066043004f4a4bb522bcd77b1b6b342796cf5ac2442d71b" +content-hash = "293620bf98bc2dd7e809af4f819b2055b895e935343e4feb5a0d5b98d2cbf46b" diff --git a/pyproject.toml b/pyproject.toml index bcb2ad6..ba5d39b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -43,9 +43,9 @@ include = [ python = "^3.8" requests = "^2.31.0" python-dateutil = "^2.8.2" -jsonschema = ">=4.17.3" +jsonschema = "^4.20.0" deprecated = "^1.2.14" -extract_msg = {version = "^0.46.2", optional = true} +extract_msg = {version = "^0.47.0", optional = true} RTFDE = {version = "^0.1.1", optional = true} oletools = {version = "^0.60.1", optional = true} python-magic = {version = "^0.4.27", optional = true} @@ -55,9 +55,9 @@ beautifulsoup4 = {version = "^4.12.2", optional = true} validators = {version = "^0.22.0", optional = true} sphinx-autodoc-typehints = {version = "^1.25.2", optional = true} recommonmark = {version = "^0.7.1", optional = true} -reportlab = {version = "^4.0.7", optional = true} +reportlab = {version = "^4.0.8", optional = true} pyfaup = {version = "^1.2", optional = true} -publicsuffixlist = {version = "^0.10.0.20231122", optional = true} +publicsuffixlist = {version = "^0.10.0.20231207", optional = true} urllib3 = {extras = ["brotli"], version = "*", optional = true} Sphinx = [ {version = "<7.2", python = "<3.9", optional = true}, From 93838661476afe793f2611e4f99e81d12a7bfb4b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 13 Dec 2023 16:48:10 +0000 Subject: [PATCH 12/80] build(deps): bump github/codeql-action from 2 to 3 Bumps [github/codeql-action](https://github.com/github/codeql-action) from 2 to 3. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/v2...v3) --- updated-dependencies: - dependency-name: github/codeql-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/codeql-analysis.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 48c35fc..f4050da 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -42,7 +42,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@v2 + uses: github/codeql-action/init@v3 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -56,7 +56,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@v2 + uses: github/codeql-action/autobuild@v3 # ℹ️ Command-line programs to run using the OS shell. # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun @@ -69,6 +69,6 @@ jobs: # ./location_of_script_within_repo/buildscript.sh - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v2 + uses: github/codeql-action/analyze@v3 with: category: "/language:${{matrix.language}}" From d96af4ad65fd7abbc152246838febb552f8a682b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Vinot?= Date: Thu, 14 Dec 2023 12:46:13 +0100 Subject: [PATCH 13/80] chg: Bump deps --- poetry.lock | 37 ++++++++++--------------------------- pyproject.toml | 2 +- 2 files changed, 11 insertions(+), 28 deletions(-) diff --git a/poetry.lock b/poetry.lock index d0d286c..8e748f8 100644 --- a/poetry.lock +++ b/poetry.lock @@ -171,18 +171,17 @@ tests-no-zope = ["cloudpickle", "hypothesis", "mypy (>=1.1.1)", "pympler", "pyte [[package]] name = "babel" -version = "2.13.1" +version = "2.14.0" description = "Internationalization utilities" optional = false python-versions = ">=3.7" files = [ - {file = "Babel-2.13.1-py3-none-any.whl", hash = "sha256:7077a4984b02b6727ac10f1f7294484f737443d7e2e66c5e4380e41a3ae0b4ed"}, - {file = "Babel-2.13.1.tar.gz", hash = "sha256:33e0952d7dd6374af8dbf6768cc4ddf3ccfefc244f9986d4074704f2fbd18900"}, + {file = "Babel-2.14.0-py3-none-any.whl", hash = "sha256:efb1a25b7118e67ce3a259bed20545c29cb68be8ad2c784c83689981b7a57287"}, + {file = "Babel-2.14.0.tar.gz", hash = "sha256:6919867db036398ba21eb5c7a0f6b28ab8cbc3ae7a73a44ebe34ae74a4e7d363"}, ] [package.dependencies] pytz = {version = ">=2015.7", markers = "python_version < \"3.9\""} -setuptools = {version = "*", markers = "python_version >= \"3.12\""} [package.extras] dev = ["freezegun (>=1.0,<2.0)", "pytest (>=6.0)", "pytest-cov"] @@ -2001,13 +2000,13 @@ twisted = ["twisted"] [[package]] name = "prompt-toolkit" -version = "3.0.41" +version = "3.0.43" description = "Library for building powerful interactive command lines in Python" optional = false python-versions = ">=3.7.0" files = [ - {file = "prompt_toolkit-3.0.41-py3-none-any.whl", hash = "sha256:f36fe301fafb7470e86aaf90f036eef600a3210be4decf461a5b1ca8403d3cb2"}, - {file = "prompt_toolkit-3.0.41.tar.gz", hash = "sha256:941367d97fc815548822aa26c2a269fdc4eb21e9ec05fc5d447cf09bad5d75f0"}, + {file = "prompt_toolkit-3.0.43-py3-none-any.whl", hash = "sha256:a11a29cb3bf0a28a387fe5122cdb649816a957cd9261dcedf8c9f1fef33eacf6"}, + {file = "prompt_toolkit-3.0.43.tar.gz", hash = "sha256:3527b7af26106cbc65a040bcc84839a3566ec1b051bb0bfe953631e704b0ff7d"}, ] [package.dependencies] @@ -2054,13 +2053,13 @@ files = [ [[package]] name = "publicsuffixlist" -version = "0.10.0.20231207" +version = "0.10.0.20231214" description = "publicsuffixlist implement" optional = true python-versions = ">=2.6" files = [ - {file = "publicsuffixlist-0.10.0.20231207-py2.py3-none-any.whl", hash = "sha256:b23f00837f898d13311f5c648759acb4c2f4dc20fe6028839a4e1a60bac5ff7d"}, - {file = "publicsuffixlist-0.10.0.20231207.tar.gz", hash = "sha256:fea76083417296f62b2e5204ab35c5c1ac615c23f50c2865056bc9420653ade3"}, + {file = "publicsuffixlist-0.10.0.20231214-py2.py3-none-any.whl", hash = "sha256:10e227902e3b2acefb604b5de8a8a7d3df237f2885f06762d47fdbc9e0528b67"}, + {file = "publicsuffixlist-0.10.0.20231214.tar.gz", hash = "sha256:76a2ed46814f091ea867fb40a6c20c142a437af7aae7ac8eb425ddc464bcb8e1"}, ] [package.extras] @@ -2699,22 +2698,6 @@ nativelib = ["pyobjc-framework-Cocoa", "pywin32"] objc = ["pyobjc-framework-Cocoa"] win32 = ["pywin32"] -[[package]] -name = "setuptools" -version = "69.0.2" -description = "Easily download, build, install, upgrade, and uninstall Python packages" -optional = false -python-versions = ">=3.8" -files = [ - {file = "setuptools-69.0.2-py3-none-any.whl", hash = "sha256:1e8fdff6797d3865f37397be788a4e3cba233608e9b509382a2777d25ebde7f2"}, - {file = "setuptools-69.0.2.tar.gz", hash = "sha256:735896e78a4742605974de002ac60562d286fa8051a7e2299445e8e8fbb01aa6"}, -] - -[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" @@ -3514,4 +3497,4 @@ virustotal = ["validators"] [metadata] lock-version = "2.0" python-versions = "^3.8" -content-hash = "293620bf98bc2dd7e809af4f819b2055b895e935343e4feb5a0d5b98d2cbf46b" +content-hash = "d424bb1bb0e2d19be80879d794f7b560d373c675071e09ab4c9dee33ba684b0f" diff --git a/pyproject.toml b/pyproject.toml index ba5d39b..eb8f769 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -57,7 +57,7 @@ sphinx-autodoc-typehints = {version = "^1.25.2", optional = true} recommonmark = {version = "^0.7.1", optional = true} reportlab = {version = "^4.0.8", optional = true} pyfaup = {version = "^1.2", optional = true} -publicsuffixlist = {version = "^0.10.0.20231207", optional = true} +publicsuffixlist = {version = "^0.10.0.20231214", optional = true} urllib3 = {extras = ["brotli"], version = "*", optional = true} Sphinx = [ {version = "<7.2", python = "<3.9", optional = true}, From c1f860dc4745a3e903b96faee62099f8be7eddb3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Vinot?= Date: Thu, 14 Dec 2023 12:48:26 +0100 Subject: [PATCH 14/80] chg: Bump objects --- pymisp/data/misp-objects | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pymisp/data/misp-objects b/pymisp/data/misp-objects index c18a240..587b298 160000 --- a/pymisp/data/misp-objects +++ b/pymisp/data/misp-objects @@ -1 +1 @@ -Subproject commit c18a240153cbe9ef68e46f05565d08653c2ad103 +Subproject commit 587b298e1e7f87426182d55d44aa045a1522dc98 From f092dfd23c126aa3e1d3bacb82423af31ad7e881 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Vinot?= Date: Thu, 14 Dec 2023 12:49:48 +0100 Subject: [PATCH 15/80] chg: Bump version --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index eb8f769..e804cb7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "pymisp" -version = "2.4.179" +version = "2.4.182" description = "Python API for MISP." authors = ["Raphaël Vinot "] license = "BSD-2-Clause" From 190f82923687cebaf06138724e7c03239e529cb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Vinot?= Date: Thu, 14 Dec 2023 12:50:56 +0100 Subject: [PATCH 16/80] chg: Bump changelog --- CHANGELOG.txt | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index a9015d4..f09ba64 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -2,11 +2,45 @@ Changelog ========= +v2.4.182 (2023-12-14) +--------------------- + +Changes +~~~~~~~ +- Bump version. [Raphaël Vinot] +- Bump objects. [Raphaël Vinot] +- Bump deps. [Raphaël Vinot] +- Bump deps. [Raphaël Vinot] +- Bump deps. [Raphaël Vinot] +- Bump deps. [Raphaël Vinot] + +Fix +~~~ +- Avoid exception when the malware file name contains a "|" [Raphaël + Vinot] + +Other +~~~~~ +- Build(deps): bump actions/setup-python from 4 to 5. [dependabot[bot]] + + Bumps [actions/setup-python](https://github.com/actions/setup-python) from 4 to 5. + - [Release notes](https://github.com/actions/setup-python/releases) + - [Commits](https://github.com/actions/setup-python/compare/v4...v5) + + --- + updated-dependencies: + - dependency-name: actions/setup-python + dependency-type: direct:production + update-type: version-update:semver-major + ... + + v2.4.179 (2023-11-23) --------------------- Changes ~~~~~~~ +- Bump version, changelog. [Raphaël Vinot] - Bump deps. [Raphaël Vinot] - Bump deps. [Raphaël Vinot] - [misp-objects] Bumped latest version. [Christian Studer] From 51433ff08aa67bd26eea50329ab41d6d804cba6e Mon Sep 17 00:00:00 2001 From: Steven Date: Fri, 15 Dec 2023 10:38:01 +0100 Subject: [PATCH 17/80] Add HTTPS Adapter Add the ability to provide a custom HTTPS adapter to the PyMISP class. With M2Crypto and m2requests, this can enable mutual TLS with hardware tokens. --- pymisp/api.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/pymisp/api.py b/pymisp/api.py index 216610a..68c9b7d 100644 --- a/pymisp/api.py +++ b/pymisp/api.py @@ -151,13 +151,15 @@ class PyMISP: :param auth: The auth parameter is passed directly to requests, as described here: http://docs.python-requests.org/en/master/user/authentication/ :param tool: The software using PyMISP (string), used to set a unique user-agent :param http_headers: Arbitrary headers to pass to all the requests. + :param https_adapter: Arbitrary HTTPS adapter for the requests session. :param timeout: Timeout, as described here: https://requests.readthedocs.io/en/master/user/advanced/#timeouts """ - def __init__(self, url: str, key: str, ssl: bool = True, debug: bool = False, proxies: Optional[MutableMapping[str, str]] = None, + def __init__(self, url: str, key: str, ssl: Union[bool, str] = True, debug: bool = False, proxies: Optional[MutableMapping[str, str]] = None, cert: Optional[Union[str, Tuple[str, str]]] = None, auth: Optional[AuthBase] = None, tool: str = '', timeout: Optional[Union[float, Tuple[float, float]]] = None, - http_headers: Optional[Dict[str, str]]=None + http_headers: Optional[Dict[str, str]] = None, + https_adapter: Optional[requests.adapters.BaseAdapter] = None ): if not url: @@ -174,6 +176,8 @@ class PyMISP: self.tool: str = tool self.timeout: Optional[Union[float, Tuple[float, float]]] = timeout self.__session = requests.Session() # use one session to keep connection between requests + if https_adapter is not None: + self.__session.mount('https://', https_adapter) if brotli_supported(): self.__session.headers['Accept-Encoding'] = ', '.join(('br', 'gzip', 'deflate')) if http_headers: From 00df6e23fbd55f2137f9d549cbc6652c7aeebc54 Mon Sep 17 00:00:00 2001 From: Steven Date: Fri, 15 Dec 2023 11:19:28 +0100 Subject: [PATCH 18/80] Fix api ssl verify typing --- pymisp/api.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pymisp/api.py b/pymisp/api.py index 68c9b7d..baceea7 100644 --- a/pymisp/api.py +++ b/pymisp/api.py @@ -169,7 +169,7 @@ class PyMISP: self.root_url: str = url self.key: str = key - self.ssl: bool = ssl + self.ssl: Union[bool, str] = ssl self.proxies: Optional[MutableMapping[str, str]] = proxies self.cert: Optional[Union[str, Tuple[str, str]]] = cert self.auth: Optional[AuthBase] = auth From afa980951f6c022e18f1a00188e2537186c9a413 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Vinot?= Date: Tue, 19 Dec 2023 14:35:28 +0100 Subject: [PATCH 19/80] new: Documentation to install PyMISP on offline machine --- README.md | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/README.md b/README.md index 39f2855..5c1509f 100644 --- a/README.md +++ b/README.md @@ -159,6 +159,35 @@ Your new MISPObject generator must generate attributes and add them as class pro When the object is sent to MISP, all the class properties will be exported to the JSON export. +## Installing PyMISP on a machine with no internet access + +This is done using poetry and you need to have this repository cloned on your machine. +The commands below have to be run from inside the cloned directory. + + +1. From a machine with access to the internet, get the dependencies: + +```bash +mkdir offline +poetry export --all-extras > offline/requirements.txt +poetry run pip download -r offline/requirements.txt -d offline/packages/ +``` + +2. Prepare the PyMISP Package + +```bash +poetry build +mv dist/*.whl offline/packages/ +``` + +2. Copy the content of `offline/packages/` to the machine with no internet access. + +3. Install the packages: + +```bash +python -m pip install --no-index --no-deps packages/*.whl +``` + # License PyMISP is distributed under an [open source license](./LICENSE). A simplified 2-BSD license. From 260caf41d6cf6a00e79ffff6a863ff64ff591d1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Vinot?= Date: Sat, 23 Dec 2023 14:20:57 +0100 Subject: [PATCH 20/80] chg: encrypt malicious js --- tests/email_testfiles/mail_1.eml | 858 --------------------------- tests/email_testfiles/mail_1.eml.zip | Bin 0 -> 27186 bytes tests/test_emailobject.py | 30 +- 3 files changed, 20 insertions(+), 868 deletions(-) delete mode 100644 tests/email_testfiles/mail_1.eml create mode 100644 tests/email_testfiles/mail_1.eml.zip diff --git a/tests/email_testfiles/mail_1.eml b/tests/email_testfiles/mail_1.eml deleted file mode 100644 index d2ae7e9..0000000 --- a/tests/email_testfiles/mail_1.eml +++ /dev/null @@ -1,858 +0,0 @@ -Return-Path: -Delivered-To: kinney@noth.com -Received: (qmail 11769 invoked from network); 22 Aug 2016 14:23:01 -0000 -Received: from smtprelay0207.b.hostedemail.com (HELO smtprelay.b.hostedemail.com) (64.98.42.207) - by smtp.server.net with SMTP; 22 Aug 2016 14:23:01 -0000 -Received: from filter.hostedemail.com (10.5.19.248.rfc1918.com [10.5.19.248]) - by smtprelay06.b.hostedemail.com (Postfix) with ESMTP id 2CC378D014 - for ; Mon, 22 Aug 2016 14:22:58 +0000 (UTC) -Received: from DM6PR06MB4475.namprd06.prod.outlook.com (2603:10b6:207:3d::31) - by BL0PR06MB4465.namprd06.prod.outlook.com with HTTPS id 12345 via - BL0PR02CA0054.NAMPRD02.PROD.OUTLOOK.COM; Mon, 1 Oct 2018 09:49:22 +0000 -Received: from DM3NAM03FT035.eop-NAM03.prod.protection.outlook.com - (2a01:111:f400:7e49::205) by CY4PR0601CA0051.outlook.office365.com - (2603:10b6:910:89::28) with Microsoft SMTP Server (version=TLS1_2, - cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384) id 15.20.1185.23 via Frontend - Transport; Mon, 1 Oct 2018 09:49:21 +0000 -X-Session-Marker: 6A64617A657940616C6578616E646572736D6974682E636F6D -X-Spam-Summary: 69,4.5,0,,d41d8cd98f00b204,suvorov.s@nalg.ru,:,RULES_HIT:46:150:152:379:553:871:967:989:1000:1254:1260:1263:1313:1381:1516:1517:1520:1575:1594:1605:1676:1699:1730:1747:1764:1777:1792:1823:2044:2197:2199:2393:2525:2560:2563:2682:2685:2827:2859:2911:2933:2937:2939:2942:2945:2947:2951:2954:3022:3867:3872:3890:3934:3936:3938:3941:3944:3947:3950:3953:3956:3959:4425:5007:6001:6261:6506:6678:6747:6748:7281:7398:7688:8599:8824:8957:9009:9025:9388:10004:10848:11604:11638:11639:11783:11914:12043:12185:12445:12517:12519:12740:13026:14149:14381:14658:14659:14687:21080:21221:30054:30055:30065:30066,0,RBL:none,CacheIP:none,Bayesian:0.5,0.5,0.5,Netcheck:none,DomainCache:0,MSF:not bulk,SPF:fn,MSBL:0,DNSBL:none,Custom_rules:0:0:0,LFtime:5,LUA_SUMMARY:none -X-HE-Tag: print38_7083d7fd63e24 -X-Filterd-Recvd-Size: 64695 -Received: from computer_3436 (unknown [43.230.105.145]) - (Authenticated sender: jdazey@alexandersmith.com) - by omf06.b.hostedemail.com (Postfix) with ESMTPA - for ; Mon, 22 Aug 2016 14:22:52 +0000 (UTC) -From: =?UTF-8?B?0YHQu9GD0LbQsdCwINCk0J3QoSDQlNCw0L3QuNC40Lsg0KHRg9Cy0L7RgNC+0LI=?= -To: kinney@noth.com -Subject: =?UTF-8?B?0L/QuNGB0YzQvNC+INGD0LLQtdC00L7QvC3QtQ==?= -Content-Type: multipart/mixed; boundary="2NqJR3m2cLnhEraiqXA4Q9hqnmihx7b7" - ---2NqJR3m2cLnhEraiqXA4Q9hqnmihx7b7 -Content-Type: text/html; charset=UTF-8 -Content-Transfer-Encoding: base64 - -0J3QsNC70L7Qs9C+0L/Qu9Cw0YLQtdC70YzRidC40LohPGJyPg0K0JjQvdGE0L7RgNC80LjRgNGD -0LXQvCDQktCw0YEg0L7QsSDQuNC80LXRjtGJ0LXQudGB0Y8g0LfQsNC00L7Qu9C20LXQvdC90L7R -gdGC0LguPHA+DQrQn9GA0L7RgdGM0LHQsCDQvtC30L3QsNC60L7QvNC40YLRjNGB0Y8g0LIg0L/R -gNC40LvQvtC20LXQvdC40LguPHA+DQo8YnI+DQo8YnI+DQrQoSDRg9Cy0LDQttC10L3QuNC10Lws -PHA+DQrQuNC90YHQv9C10LrRgtC+0YAg0KTQndChINCg0KQg0JXQs9C+0YAg0KHRg9Cy0L7RgNC+ -0LIuPGJyPg0KPHA+DQo8YnI+DQo8cD4NCjxwPg0K0JjQvdGE0L7RgNC80LDRhtC40L7QvdC90YvQ -uSDRgNCw0LfQtNC10Ls8YnI+DQo8YnI+DQrQn9GA0LXQt9C40LTQtdC90YIg0L/QvtGA0YPRh9C4 -0Lsg0L/RgNCw0LLQuNGC0LXQu9GM0YHRgtCy0YMg0LfQsNC60YDQtdC/0LjRgtGMINCyINC30LDQ -utC+0L3QtSDRgNC40YHQui3QvtGA0LjQtdC90YLQuNGA0L7QstCw0L3QvdGL0Lkg0L/QvtC00YXQ -vtC0INC6INC/0YDQvtCy0LXRgNC60LDQvDxwPg0KPHA+DQoxNSDQsNCy0LPRg9GB0YLQsCAyMDE2 -PGJyPg0K0JLQsNC70LXRgNC40Y8g0JfQtdC90L7QstC40L3QsDxicj4NCjxwPg0K0J/RgNC10LfQ -uNC00LXQvdGCINC/0L7RgNGD0YfQuNC7INC/0YDQsNCy0LjRgtC10LvRjNGB0YLQstGDINC30LDQ -utGA0LXQv9C40YLRjCDQsiDQt9Cw0LrQvtC90LUg0YDQuNGB0Lot0L7RgNC40LXQvdGC0LjRgNC+ -0LLQsNC90L3Ri9C5INC/0L7QtNGF0L7QtCDQuiDQv9GA0L7QstC10YDQutCw0LzQktCy0LXRgdGC -0Lgg0YLQsNC60L7QuSDQv9C+0LTRhdC+0LQg0L/RgNC4INC+0YDQs9Cw0L3QuNC30LDRhtC40Lgg -0LrQvtC90YLRgNC+0LvRjNC90L4t0L3QsNC00LfQvtGA0L3Ri9GFINC80LXRgNC+0L/RgNC40Y/R -gtC40Lkg0Lgg0LIg0YbQtdC70L7QvCDQvtC/0YLQuNC80LjQt9C40YDQvtCy0LDRgtGMINC/0L7Q -tNC+0LHQvdGL0LUg0LzQtdGA0L7Qv9GA0LjRj9GC0LjRjyDQvdCwINGA0LXQs9C40L7QvdCw0LvR -jNC90L7QvCDQuCDQvNGD0L3QuNGG0LjQv9Cw0LvRjNC90L7QvCDRg9GA0L7QstC90Y/RhSDQn9GA -0LXQt9C40LTQtdC90YIg0KDQpCDQktC70LDQtNC40LzQuNGAINCf0YPRgtC40L0g0L/QvtGA0YPR -h9C40Lsg0LrQsNCx0LzQuNC90YMg0LTQviAzMSDQtNC10LrQsNCx0YDRjyDRgtC10LrRg9GJ0LXQ -s9C+INCz0L7QtNCwLiDQmNC30LzQtdC90LXQvdC40Y8g0LzQvtCz0YPRgiDQutC+0YHQvdGD0YLR -jNGB0Y8g0Lgg0LLQvdC10L/Qu9Cw0L3QvtCy0YvRhSDQv9GA0L7QstC10YDQvtC6LiDQkiDRgdC+ -0L7RgtCy0LXRgtGB0YLQstC40Lgg0YEg0YPQutCw0LfQsNC90LjRj9C80Lgg0L/RgNC10LfQuNC0 -0LXQvdGC0LAsINCT0LXQvdC10YDQsNC70YzQvdCw0Y8g0L/RgNC+0LrRg9GA0LDRgtGD0YDQsCDQ -oNCkINC00L7Qu9C20L3QsCDQstC90LXRgdGC0Lgg0LIg0LfQsNC60L7QvdC+0LTQsNGC0LXQu9GM -0YHRgtCy0L4g0L/QvtC/0YDQsNCy0LrQuCwg0L/RgNC10LTRg9GB0LzQsNGC0YDQuNCy0LDRjtGJ -0LjQtSDRgdC+0LPQu9Cw0YHQvtCy0LDQvdC40LUg0YLQsNC60LjRhSDQv9GA0L7QstC10YDQvtC6 -INGBINC+0YDQs9Cw0L3QsNC80Lgg0L/RgNC+0LrRg9GA0LDRgtGD0YDRiy4g0K3RgtC+INC30LDR -gtGA0L7QvdC10YIg0L/RgNC+0LLQtdGA0LrQuCwg0LjQvdC40YbQuNC40YDRg9C10LzRi9C1INCy -INGB0LLRj9C30Lgg0YEg0L3QsNGA0YPRiNC10L3QuNC10Lwg0L/RgNCw0LIg0L/QvtGC0YDQtdCx -0LjRgtC10LvQtdC5LCDQuCDQvdC10LrQvtGC0L7RgNGL0LUg0LTRgNGD0LPQuNC1LjxwPg0KPGJy -Pg0K0J3QsNGA0Y/QtNGDINGBINGN0YLQuNC8LCDRgNGP0LQg0LfQsNC60L7QvdC+0LTQsNGC0LXQ -u9GM0L3Ri9GFINC40LfQvNC10L3QtdC90LjQuSDQvNC+0LbQtdGCINC60L7RgdC90YPRgtGM0YHR -jyDQtdC00LjQvdC+0LPQviDRgNC10LXRgdGC0YDQsCDQv9GA0L7QstC10YDQvtC6IChwcm92ZXJr -aS5nb3YucnUpLjxwPg0KPGJyPg0K0KLQsNC6LCDQvtGA0LPQsNC90YssINGA0LXQsNC70LjQt9GD -0Y7RidC40LUg0LrQvtC90YLRgNC+0LvRjNC90L4t0L3QsNC00LfQvtGA0L3Ri9C1INC/0L7Qu9C9 -0L7QvNC+0YfQuNGPLCDQtNC+0LvQttC90Ysg0LHRg9C00YPRgiDQv9C+INGB0L7Qs9C70LDRgdC+ -0LLQsNC90LjRjiDRgSDQk9C10L3QtdGA0LDQu9GM0L3QvtC5INC/0YDQvtC60YPRgNCw0YLRg9GA -0L7QuSDQoNCkINGA0LDQt9GA0LDQsdC+0YLQsNGC0Ywg0Lgg0LjQt9C00LDRgtGMINCw0LrRgtGL -LCDRgNC10LPQu9Cw0LzQtdC90YLQuNGA0YPRjtGJ0LjQtSDQv9C+0YDRj9C00L7QuiDQstC90LXR -gdC10L3QuNGPINC40L3RhNC+0YDQvNCw0YbQuNC4INC+INC/0YDQvtCy0LXRgNC60LDRhSDQsiDQ -tdC00LjQvdGL0Lkg0YDQtdC10YHRgtGAINC/0YDQvtCy0LXRgNC+0LouINCQINC30LAg0L3QtdCy -0L3QtdGB0LXQvdC40LUg0YLQsNC60LjRhSDRgdCy0LXQtNC10L3QuNC5INC4INC30LAg0L3QsNGA -0YPRiNC10L3QuNC1INC/0L7RgNGP0LTQutCwINC4INGB0YDQvtC60L7QsiDQuNGFINCy0L3QtdGB -0LXQvdC40Y8g0L/RgNC10LTQu9Cw0LPQsNC10YLRgdGPINGD0YHRgtCw0L3QvtCy0LjRgtGMINCw -0LTQvNC40L3QuNGB0YLRgNCw0YLQuNCy0L3Rg9GOINC+0YLQstC10YLRgdGC0LLQtdC90L3QvtGB -0YLRjC4g0JrQsNC60LjQtSDQuNC80LXQvdC90L4g0L3QsNC60LDQt9Cw0L3QuNGPINC80L7Qs9GD -0YIg0LHRi9GC0Ywg0LLQstC10LTQtdC90Ysg0LIg0JrQvtCQ0J8g0KDQpCDigJMg0L3QtSDRg9GC -0L7Rh9C90Y/QtdGC0YHRjy4g0J7QttC40LTQsNC10YLRgdGPLCDRh9GC0L4g0YPQutCw0LfQsNC9 -0L3Ri9C1INC/0L7RgNGD0YfQtdC90LjRjyDQsdGD0LTRg9GCINC40YHQv9C+0LvQvdC10L3RiyDQ -uiAxINC00LXQutCw0LHRgNGPLjxicj4NCjxwPg0K0JrRgNC+0LzQtSDRgtC+0LPQviwg0LTQviAx -NSDQtNC10LrQsNCx0YDRjyDQk9C10L3QtdGA0LDQu9GM0L3QvtC5INC/0YDQvtC60YPRgNCw0YLR -g9GA0LUg0KDQpCDQvdC10L7QsdGF0L7QtNC40LzQviDQsdGD0LTQtdGCINC00L7RgNCw0LHQvtGC -0LDRgtGMINC10LTQuNC90YvQuSDRgNC10LXRgdGC0YAg0L/RgNC+0LLQtdGA0L7QuiDRgtCw0Los -INGH0YLQvtCx0Ysg0L/RgNC4INCy0L3QtdGB0LXQvdC40Lgg0LIg0L3QtdCz0L4g0LjQvdGE0L7R -gNC80LDRhtC40Lgg0YHRgtCw0LvQviDQstC+0LfQvNC+0LbQvdGL0Lwg0LjRgdC/0L7Qu9GM0LfQ -vtCy0LDQvdC40LUg0YHQstC10LTQtdC90LjQuSDQuNC3INC00YDRg9Cz0LjRhSDQs9C+0YHRg9C0 -0LDRgNGB0YLQstC10L3QvdGL0YUg0LjQvdGE0L7RgNC80LDRhtC40L7QvdC90YvRhSDRgdC40YHR -gtC10LwsINGB0L/RgNCw0LLQvtGH0L3QuNC60L7QsiDQuCDQutC70LDRgdGB0LjRhNC40LrQsNGC -0L7RgNC+0LIuINCi0LDQutC20LUg0LPQu9Cw0LLQsCDQs9C+0YHRg9C00LDRgNGB0YLQstCwINGD -0LrQsNC30LDQuywg0YfRgtC+INC90LXQvtCx0YXQvtC00LjQvNCwINGE0L7RgNC80LDQu9C40LfQ -sNGG0LjRjyDQuCDQutC+0L3QutGA0LXRgtC40LfQsNGG0LjRjyDQstC90L7RgdC40LzQvtC5INCy -INGA0LXQtdGB0YLRgCDQuNC90YTQvtGA0LzQsNGG0LjQuCwg0LXRgdC70Lgg0L7QvdCwINC60LDR -gdCw0LXRgtGB0Y8g0L/RgNCw0LLQvtCy0YvRhSDQvtGB0L3QvtCy0LDQvdC40Lkg0LTQu9GPINC+ -0YDQs9Cw0L3QuNC30LDRhtC40Lgg0L/RgNC+0LLQtdGA0L7Qui4g0KDQtdGH0Ywg0LjQtNC10YIg -0Lgg0L4g0YTQvtGA0LzQsNC70LjQt9Cw0YbQuNC4INGC0YDQtdCx0L7QstCw0L3QuNC5LCDRgdC+ -0LHQu9GO0LTQtdC90LjQtSDQutC+0YLQvtGA0YvRhSDQvtGG0LXQvdC40LLQsNC10YLRgdGPINC/ -0YDQuCDQv9GA0L7QstC10LTQtdC90LjQuCDRgdC+0L7RgtCy0LXRgtGB0YLQstGD0Y7RidC40YUg -0LzQtdGA0L7Qv9GA0LjRj9GC0LjQuSwg0LAg0YLQsNC60LbQtSDRgNC10LfRg9C70YzRgtCw0YLQ -vtCyINC/0YDQvtCy0LXRgNC+0Log0Lgg0L/RgNC40L3Rj9GC0YvRhSDQvNC10YAuPHA+DQo8YnI+ -DQrQn9C+0LzQuNC80L4g0Y3RgtC+0LPQviDQv9GA0LXQt9C40LTQtdC90YIg0L/QvtGA0YPRh9C4 -0Lsg0L/RgNCw0LLQuNGC0LXQu9GM0YHRgtCy0YMg0YDQsNGB0YHQvNC+0YLRgNC10YLRjCDQstC+ -0L/RgNC+0YEg0L4g0YHRgtC40LzRg9C70LjRgNGD0Y7RidC40YUg0LLRi9C/0LvQsNGC0LDRhSDQ -tNC70Y8g0YHQvtGC0YDRg9C00L3QuNC60L7QsiDRhNC10LTQtdGA0LDQu9GM0L3Ri9GFINC40YHQ -v9C+0LvQvdC40YLQtdC70YzQvdGL0YUg0L7RgNCz0LDQvdC+0LIsINC60L7RgtC+0YDRi9C1INC+ -0YHRg9GJ0LXRgdGC0LLQu9GP0Y7RgiDQv9GA0L7QstC10YDQutC4LjxwPg0KPGJyPg0K0J/QviDR -gNC10LfRg9C70YzRgtCw0YLQsNC8INGN0LvQtdC60YLRgNC+0L3QvdC+0LPQviDQsNGD0LrRhtC4 -0L7QvdCwINC30LDQutC70Y7Rh9Cw0YLRjCDQutC+0L3RgtGA0LDQutGCINC90LAg0LHRg9C80LDQ -s9C1INC90LUg0L3Rg9C20L3Qvjxicj4NCjxwPg0KMTIg0LDQstCz0YPRgdGC0LAgMjAxNjxicj4N -CtCS0LDQu9C10YDQuNGPINCX0LXQvdC+0LLQuNC90LA8cD4NCjxicj4NCtCf0L4g0YDQtdC30YPQ -u9GM0YLQsNGC0LDQvCDRjdC70LXQutGC0YDQvtC90L3QvtCz0L4g0LDRg9C60YbQuNC+0L3QsCDQ -t9Cw0LrQu9GO0YfQsNGC0Ywg0LrQvtC90YLRgNCw0LrRgiDQvdCwINCx0YPQvNCw0LPQtSDQvdC1 -INC90YPQttC90L7QnNC40L3RjdC60L7QvdC+0LzRgNCw0LfQstC40YLQuNGPINGA0LDQt9GK0Y/R -gdC90LjQu9C+LCDRh9GC0L4g0L/QviDRgNC10LfRg9C70YzRgtCw0YLQsNC8INGN0LvQtdC60YLR -gNC+0L3QvdC+0LPQviDQsNGD0LrRhtC40L7QvdCwINC/0YDQuCDQvdCw0LvQuNGH0LjQuCDQt9Cw -0LrQu9GO0YfQtdC90L3QvtCz0L4g0LrQvtC90YLRgNCw0LrRgtCwINCyINGN0LvQtdC60YLRgNC+ -0L3QvdC+0Lkg0YTQvtGA0LzQtSDQt9Cw0LrQu9GO0YfQsNGC0Ywg0LrQvtC90YLRgNCw0LrRgiDQ -tdGJ0LUg0Lgg0LIg0L/QuNGB0YzQvNC10L3QvdC+0Lkg0YTQvtGA0LzQtSDQvdCwINCx0YPQvNCw -0LbQvdC+0Lwg0L3QvtGB0LjRgtC10LvQtSDQvdC1INC90YPQttC90L4uINCS0LXQtNC+0LzRgdGC -0LLQviDQv9C+0LTRh9C10YDQutC90YPQu9C+LCDRh9GC0L4g0YLQsNC60LDRjyDQvdC10L7QsdGF -0L7QtNC40LzQvtGB0YLRjCDQvdC1INC/0YDQtdC00YPRgdC80L7RgtGA0LXQvdCwINC00LXQudGB -0YLQstGD0Y7RidC40Lwg0LfQsNC60L7QvdC+0LTQsNGC0LXQu9GM0YHRgtCy0L7QvCAo0L/QuNGB -0YzQvNC+INCc0LjQvdGN0LrQvtC90L7QvNGA0LDQt9Cy0LjRgtC40Y8g0KDQvtGB0YHQuNC4INC+ -0YIgNSDQuNGO0LvRjyAyMDE2INCzLiDihJYg0JQyONC4LTE2ODcpLjxwPg0KPHA+DQrQodC10LPQ -vtC00L3RjyDQtNC70Y8g0YLQvtCz0L4sINGH0YLQvtCx0Ysg0LfQsNC60LvRjtGH0LjRgtGMINGN -0LvQtdC60YLRgNC+0L3QvdGL0Lkg0LrQvtC90YLRgNCw0LrRgiDQvdCwINGN0LvQtdC60YLRgNC+ -0L3QvdC+0Lwg0LDRg9C60YbQuNC+0L3QtSwg0LXQs9C+INC90LXQvtCx0YXQvtC00LjQvNC+INGA -0LDQt9C80LXRgdGC0LjRgtGMINCyINC10LTQuNC90L7QuSDQuNC90YTQvtGA0LzQsNGG0LjQvtC9 -0L3QvtC5INGB0LjRgdGC0LXQvNC1ICjQldCY0KEpLCDQv9GA0LjRh9C10Lwg0L7QvSDQtNC+0LvQ -ttC10L0g0LHRi9GC0Ywg0L/QvtC00L/QuNGB0LDQvSDRg9GB0LjQu9C10L3QvdC+0Lkg0Y3Qu9C1 -0LrRgtGA0L7QvdC90L7QuSDQv9C+0LTQv9C40YHRjNGOINC70LjRhtCwLCDQuNC80LXRjtGJ0LXQ -s9C+INC/0YDQsNCy0L4g0LTQtdC50YHRgtCy0L7QstCw0YLRjCDQvtGCINC40LzQtdC90Lgg0LfQ -sNC60LDQt9GH0LjQutCwLiDQodC00LXQu9Cw0YLRjCDRjdGC0L4g0L3QtdC+0LHRhdC+0LTQuNC8 -0L4g0LIg0YLQtdGH0LXQvdC40LUg0YLRgNC10YUg0YDQsNCx0L7Rh9C40YUg0LTQvdC10Lkg0YEg -0LTQsNGC0Ysg0YDQsNC30LzQtdGJ0LXQvdC40Y8g0L/RgNC+0LXQutGC0LAg0YLQvtCz0L4g0LbQ -tSDQutC+0L3RgtGA0LDQutGC0LAuPGJyPg0KPGJyPg0K0JIg0LrQsNC60LjRhSDRgdC70YPRh9Cw -0Y/RhSDQt9Cw0LrQsNC30YfQuNC6INC+0LHRj9C30LDQvSDQv9GA0L7QstC+0LTQuNGC0Ywg0Y3Q -u9C10LrRgtGA0L7QvdC90YvQuSDQsNGD0LrRhtC40L7QvT8g0KPQt9C90LDQudGC0LUg0LjQtyDQ -vNCw0YLQtdGA0LjQsNC70LAgItCj0YHQu9C+0LLQuNGPINC/0YDQuNC80LXQvdC10L3QuNGPINGN -0LvQtdC60YLRgNC+0L3QvdC+0LPQviDQsNGD0LrRhtC40L7QvdCwIiDQsiAi0K3QvdGG0LjQutC7 -0L7Qv9C10LTQuNC4INGA0LXRiNC10L3QuNC5LiDQk9C+0YHRg9C00LDRgNGB0YLQstC10L3QvdGL -0LUg0Lgg0LrQvtGA0L/QvtGA0LDRgtC40LLQvdGL0LUg0LfQsNC60YPQv9C60LgiINC40L3RgtC1 -0YDQvdC10YIt0LLQtdGA0YHQuNC4INGB0LjRgdGC0LXQvNGLINCT0JDQoNCQ0J3Qoi4g0J/QvtC7 -0YPRh9C40YLQtSDQv9C+0LvQvdGL0Lkg0LTQvtGB0YLRg9C/INC90LAgMyDQtNC90Y8g0LHQtdGB -0L/Qu9Cw0YLQvdC+ITxwPg0K0J/QvtC70YPRh9C40YLRjCDQtNC+0YHRgtGD0L88cD4NCtCj0LrQ -sNC30LDQvdC90YvQuSDQv9GA0L7QtdC60YIg0L/RgNC4INGN0YLQvtC8INGC0L7QttC1INC00L7Q -u9C20LXQvSDQsdGL0YLRjCDQv9C+0LTQv9C40YHQsNC9INGD0YHQuNC70LXQvdC90L7QuSDRjdC7 -0LXQutGC0YDQvtC90L3QvtC5INC/0L7QtNC/0LjRgdGM0Y4sINC90L4g0YPQttC1INC70LjRhtCw -LCDQutC+0YLQvtGA0L7QtSDQuNC80LXQtdGCINC/0YDQsNCy0L4g0LTQtdC50YHRgtCy0L7QstCw -0YLRjCDQvtGCINC40LzQtdC90Lgg0L/QvtCx0LXQtNC40YLQtdC70Y8g0Y3Qu9C10LrRgtGA0L7Q -vdC90L7Qs9C+INCw0YPQutGG0LjQvtC90LAuINCf0L7QvNC40LzQviDQv9GA0L7QtdC60YLQsCDQ -utC+0L3RgtGA0LDQutGC0LAg0YLQsNC60L7QuSDQv9C+0LHQtdC00LjRgtC10LvRjCDQtNC+0LvQ -ttC10L0g0L/RgNC10LTQvtGB0YLQsNCy0LjRgtGMINC+0LHQtdGB0L/QtdGH0LXQvdC40LUg0LjR -gdC/0L7Qu9C90LXQvdC40Y8g0LrQvtC90YLRgNCw0LrRgtCwICjRhy4gNyDRgdGCLiA3MCDQpNC1 -0LTQtdGA0LDQu9GM0L3QvtCz0L4g0LfQsNC60L7QvdCwINC+0YIgNSDQsNC/0YDQtdC70Y8gMjAx -MyDQsy4g4oSWIDQ0LdCk0JcgItCeINC60L7QvdGC0YDQsNC60YLQvdC+0Lkg0YHQuNGB0YLQtdC8 -0LUg0LIg0YHRhNC10YDQtSDQt9Cw0LrRg9C/0L7QuiDRgtC+0LLQsNGA0L7Qsiwg0YDQsNCx0L7R -giwg0YPRgdC70YPQsyDQtNC70Y8g0L7QsdC10YHQv9C10YfQtdC90LjRjyDQs9C+0YHRg9C00LDR -gNGB0YLQstC10L3QvdGL0YUg0Lgg0LzRg9C90LjRhtC40L/QsNC70YzQvdGL0YUg0L3Rg9C20LQi -OyDQtNCw0LvQtdC1IOKAkyDQl9Cw0LrQvtC9IOKEliA0NC3QpNCXKS48cD4NCjxicj4NCtChINC8 -0L7QvNC10L3RgtCwINGA0LDQt9C80LXRidC10L3QuNGPINCyINCV0JjQoSDQv9C+0LTQv9C40YHQ -sNC90L3QvtCz0L4g0LfQsNC60LDQt9GH0LjQutC+0Lwg0LrQvtC90YLRgNCw0LrRgtCwINC+0L0g -0YHRh9C40YLQsNC10YLRgdGPINC30LDQutC70Y7Rh9C10L3QvdGL0LwgKNGHLiA4INGB0YIuIDcw -INCX0LDQutC+0L3QsCDihJYgNDQt0KTQlykuPGJyPg0KPGJyPg0K0J3QsNC/0L7QvNC90LjQvCwg -0L/QviDQtNC10LnRgdGC0LLRg9GO0YnQtdC80YMg0LfQsNC60L7QvdC+0LTQsNGC0LXQu9GM0YHR -gtCy0YMsINGN0LvQtdC60YLRgNC+0L3QvdGL0Lkg0LDRg9C60YbQuNC+0L0g0L/RgNC+0LLQvtC0 -0LjRgtGB0Y8g0L/Rg9GC0LXQvCDRgdC90LjQttC10L3QuNGPINC90LDRh9Cw0LvRjNC90L7QuSAo -0LzQsNC60YHQuNC80LDQu9GM0L3QvtC5KSDRhtC10L3RiyDQutC+0L3RgtGA0LDQutGC0LAsINGD -0LrQsNC30LDQvdC90L7QuSDQsiDQuNC30LLQtdGJ0LXQvdC40Lgg0L4g0L/RgNC+0LLQtdC00LXQ -vdC40Lgg0YLQsNC60L7Qs9C+INCw0YPQutGG0LjQvtC90LAuINCSINC90LXQvCDQvNC+0LPRg9GC -INGD0YfQsNGB0YLQstC+0LLQsNGC0Ywg0YLQvtC70YzQutC+INCw0LrQutGA0LXQtNC40YLQvtCy -0LDQvdC90YvQtSDRg9GH0LDRgdGC0L3QuNC60LgsINCwINC80LXRgdGC0L7QvCDQtdCz0L4g0L/R -gNC+0LLQtdC00LXQvdC40Y8g0Y/QstC70Y/QtdGC0YHRjyDRjdC70LXQutGC0YDQvtC90L3QsNGP -INC/0LvQvtGJ0LDQtNC60LAgKNGB0YIuIDY4INCX0LDQutC+0L3QsCDihJYgNDQt0KTQlykuPGJy -Pg0KPHA+DQo1INC00LXQutCw0LHRgNGPIDIwMTQg0LPQvtC00LAg0YHQvtGB0YLQvtGP0LvQvtGB -0Ywg0LjQvdGC0LXRgNC90LXRgi3QuNC90YLQtdGA0LLRjNGOINGBINC90LDRh9Cw0LvRjNC90LjQ -utC+0Lwg0KPQv9GA0LDQstC70LXQvdC40Y8g0LrQsNC80LXRgNCw0LvRjNC90L7Qs9C+INC60L7Q -vdGC0YDQvtC70Y8g0KTQtdC00LXRgNCw0LvRjNC90L7QuSDQvdCw0LvQvtCz0L7QstC+0Lkg0YHQ -u9GD0LbQsdGLINCh0LDRgtC40L3Ri9C8INCU0LzQuNGC0YDQuNC10Lwg0KHRgtCw0L3QuNGB0LvQ -sNCy0L7QstC40YfQtdC8Ljxicj4NCjxicj4NCtCi0LXQvNCwINC40L3RgtC10YDQvdC10YIt0LjQ -vdGC0LXRgNCy0YzRjjogItCd0LDQu9C+0LMg0L3QsCDQtNC+0LHQsNCy0LvQtdC90L3Rg9GOINGB -0YLQvtC40LzQvtGB0YLRjDog0L3QvtCy0LDRhtC40LggMjAxNSDQs9C+0LTQsCIuPGJyPg0KPHA+ -DQrQktC10LTRg9GJ0LDRjzog0JTQvtCx0YDRi9C5INC00LXQvdGMLCDQlNC80LjRgtGA0LjQuSDQ -odGC0LDQvdC40YHQu9Cw0LLQvtCy0LjRhyEg0KDQsNGB0YHQutCw0LbQuNGC0LUsINC/0L7QttCw -0LvRg9C50YHRgtCwLCDQutCw0LrQuNC1INC90L7QstCw0YbQuNC4LCDRgdCy0Y/Qt9Cw0L3QvdGL -0LUg0YEg0L/RgNC10LTRgdGC0LDQstC70LXQvdC40LXQvCDQvtGC0YfQtdGC0L3QvtGB0YLQuCDQ -v9C+INCd0JTQoSwg0L7QttC40LTQsNGO0YIg0L3QsNC70L7Qs9C+0L/Qu9Cw0YLQtdC70YzRidC4 -0LrQvtCyINCyIDIwMTUg0LPQvtC00YM/PGJyPg0KPGJyPg0K0KHQsNGC0LjQvSDQlC7QoS46INCU -0L7QsdGA0YvQuSDQtNC10L3RjCEg0J3QsNGH0LjQvdCw0Y8g0YEg0L3QsNC70L7Qs9C+0LLQvtCz -0L4g0L/QtdGA0LjQvtC00LAg0LfQsCAxINC60LLQsNGA0YLQsNC7IDIwMTUg0LPQvtC00LAg0L3Q -sCDQvtGB0L3QvtCy0LDQvdC40Lgg0L/Rg9C90LrRgtCwIDUuMSDRgdGC0LDRgtGM0LggMTc0INCa -0L7QtNC10LrRgdCwICjQsiDRgNC10LTQsNC60YbQuNC4INCk0LXQtNC10YDQsNC70YzQvdC+0LPQ -viDQt9Cw0LrQvtC90LAg0L7RgiAyOC4wNi4yMDEzIOKEliAxMzQt0KTQlykg0LIg0L3QsNC70L7Q -s9C+0LLRg9GOINC00LXQutC70LDRgNCw0YbQuNGOINC/0L4g0J3QlNChINCy0LrQu9GO0YfQsNGO -0YLRgdGPINGB0LLQtdC00LXQvdC40Y8sINGD0LrQsNC30LDQvdC90YvQtSDQsiDQutC90LjQs9C1 -INC/0L7QutGD0L/QvtC6INC4INC60L3QuNCz0LUg0L/RgNC+0LTQsNC2LiDQn9GA0Lgg0L7RgdGD -0YnQtdGB0YLQstC70LXQvdC40Lgg0L/QvtGB0YDQtdC00L3QuNGH0LXRgdC60L7QuSDQtNC10Y/R -gtC10LvRjNC90L7RgdGC0Lgg0LIg0L3QsNC70L7Qs9C+0LLRg9GOINC00LXQutC70LDRgNCw0YbQ -uNGOINC/0L4g0J3QlNChINCy0LrQu9GO0YfQsNGO0YLRgdGPINGB0LLQtdC00LXQvdC40Y8sINGD -0LrQsNC30LDQvdC90YvQtSDQsiDQttGD0YDQvdCw0LvQtSDRg9GH0LXRgtCwINC/0L7Qu9GD0YfQ -tdC90L3Ri9GFINC4INCy0YvRgdGC0LDQstC70LXQvdC90YvRhSDRgdGH0LXRgtC+0LIt0YTQsNC6 -0YLRg9GALCDQsiDQvtGC0L3QvtGI0LXQvdC40Lgg0YPQutCw0LfQsNC90L3QvtC5INC00LXRj9GC -0LXQu9GM0L3QvtGB0YLQuC48YnI+DQo8YnI+DQrQn9GA0LjQutCw0LfQvtC8INCk0J3QoSDQoNC+ -0YHRgdC40Lgg0L7RgiAyOS4xMC4yMDE0IOKEliDQnNCc0JItNy0zLzU1OEAg0YPRgtCy0LXRgNC2 -0LTQtdC90LAg0YTQvtGA0LzQsCDQvdCw0LvQvtCz0L7QstC+0Lkg0LTQtdC60LvQsNGA0LDRhtC4 -0Lgg0L/QviDQndCU0KEsINC/0L7RgNGP0LTQvtC6INC10LUg0LfQsNC/0L7Qu9C90LXQvdC40Y8g -0Lgg0YTQvtGA0LzQsNGCINC/0YDQtdC00YHRgtCw0LLQu9C10L3QuNGPINCyINGN0LvQtdC60YLR -gNC+0L3QvdC+0Lkg0YTQvtGA0LzQtS4g0JIg0L3QsNGB0YLQvtGP0YnQtdC1INCy0YDQtdC80Y8g -0L/RgNC40LrQsNC3INC/0YDQvtGF0L7QtNC40YIg0LPQvtGB0YPQtNCw0YDRgdGC0LLQtdC90L3R -g9GOINGA0LXQs9C40YHRgtGA0LDRhtC40Y4g0LIg0JzQuNC90Y7RgdGC0LUg0KDQvtGB0YHQuNC4 -LjxwPg0KPHA+DQrQkiDQvdC+0LLQvtC5INGE0L7RgNC80LUg0L3QsNC70L7Qs9C+0LLQvtC5INC0 -0LXQutC70LDRgNCw0YbQuNC4INC/0L4g0J3QlNChINC/0YDQtdC00YPRgdC80L7RgtGA0LXQvdGL -INGA0LDQt9C00LXQu9GLLCDRgdC+0LTQtdGA0LbQsNGJ0LjQtSDRgdCy0LXQtNC10L3QuNGPINC4 -0Lcg0LrQvdC40LMg0L/QvtC60YPQv9C+0LosINC60L3QuNCzINC/0YDQvtC00LDQtiwg0LbRg9GA -0L3QsNC70L7QsiDRg9GH0LXRgtCwINC/0L7Qu9GD0YfQtdC90L3Ri9GFINC4INCy0YvRgdGC0LDQ -stC70LXQvdC90YvRhSDRgdGH0LXRgtC+0LIt0YTQsNC60YLRg9GALjxicj4NCjxicj4NCtCSINGB -0L7QvtGC0LLQtdGC0YHRgtCy0LjQuCDRgSDQv9GD0L3QutGC0L7QvCAzINGB0YLQsNGC0YzQuCA4 -MCDQuCDQv9GD0L3QutGC0L7QvCA1INGB0YLQsNGC0YzQuCAxNzQg0JrQvtC00LXQutGB0LAg0L3Q -sNC70L7Qs9C+0LLQsNGPINC00LXQutC70LDRgNCw0YbQuNGPINC/0L4g0J3QlNChINC00L7Qu9C2 -0L3QsCDQv9GA0LXQtNGB0YLQsNCy0LvRj9GC0YzRgdGPINCyINGN0LvQtdC60YLRgNC+0L3QvdC+ -0Lkg0YTQvtGA0LzQtSDQv9C+INGC0LXQu9C10LrQvtC80LzRg9C90LjQutCw0YbQuNC+0L3QvdGL -0Lwg0LrQsNC90LDQu9Cw0Lwg0YHQstGP0LfQuCDRh9C10YDQtdC3INC+0L/QtdGA0LDRgtC+0YDQ -sCDRjdC70LXQutGC0YDQvtC90L3QvtCz0L4g0LTQvtC60YPQvNC10L3RgtC+0L7QsdC+0YDQvtGC -0LAuINCi0LDQutC40Lwg0L7QsdGA0LDQt9C+0LwsINGE0L7RgNC80LjRgNC+0LLQsNC90LjQtSDQ -vdCw0LvQvtCz0L7QstC+0Lkg0LTQtdC60LvQsNGA0LDRhtC40Lgg0L/QviDQndCU0KEg0L3QsCDQ -sdGD0LzQsNC20L3Ri9GFINC90L7RgdC40YLQtdC70Y/RhSDQt9Cw0LrQvtC90L7QtNCw0YLQtdC7 -0YzRgdGC0LLQvtC8INC+INC90LDQu9C+0LPQsNGFINC4INGB0LHQvtGA0LDRhSDQvdC1INC/0YDQ -tdC00YPRgdC80L7RgtGA0LXQvdC+Ljxicj4NCjxicj4NCtCb0LjRhtCwLCDQvdC1INGP0LLQu9GP -0Y7RidC40LXRgdGPINC90LDQu9C+0LPQvtC/0LvQsNGC0LXQu9GM0YnQuNC60LDQvNC4INCd0JTQ -oSDQuNC70Lgg0L3QsNC70L7Qs9C+0LLRi9C80Lgg0LDQs9C10L3RgtCw0LzQuCDQv9C+INCd0JTQ -oSwg0L3QviDQvtGB0YPRidC10YHRgtCy0LvRj9GO0YnQuNC1INC/0L7RgdGA0LXQtNC90LjRh9C1 -0YHQutGD0Y4g0LTQtdGP0YLQtdC70YzQvdC+0YHRgtGMLCDQtNC+0LvQttC90Ysg0L3QsCDQvtGB -0L3QvtCy0LDQvdC40Lgg0L/Rg9C90LrRgtCwIDUuMiDRgdGC0LDRgtGM0LggMTc0INCa0L7QtNC1 -0LrRgdCwINC/0YDQtdC00YHRgtCw0LLQu9GP0YLRjCDQsiDQvdCw0LvQvtCz0L7QstGL0Lkg0L7R -gNCz0LDQvSDQsiDQvtGC0L3QvtGI0LXQvdC40Lgg0YPQutCw0LfQsNC90L3QvtC5INC00LXRj9GC -0LXQu9GM0L3QvtGB0YLQuCDQttGD0YDQvdCw0Lsg0YPRh9C10YLQsCDQv9C+0LvRg9GH0LXQvdC9 -0YvRhSDQuCDQstGL0YHRgtCw0LLQu9C10L3QvdGL0YUg0YHRh9C10YLQvtCyLdGE0LDQutGC0YPR -gCDQv9C+INCi0JrQoSDRh9C10YDQtdC3INC+0L/QtdGA0LDRgtC+0YDQsCDQrdCU0J4uPHA+DQo8 -cD4NCtCk0LXQtNC10YDQsNC70YzQvdC+0Lkg0L3QsNC70L7Qs9C+0LLQvtC5INGB0LvRg9C20LHQ -vtC5INGA0LDQt9GA0LDQsdC+0YLQsNC90LAg0LHQtdGB0L/Qu9Cw0YLQvdCw0Y8g0L/RgNC+0LPR -gNCw0LzQvNCwICLQndCw0LvQvtCz0L7Qv9C70LDRgtC10LvRjNGJ0LjQuiDQrtCbIiDQtNC70Y8g -0LLQtdC00LXQvdC40Y8g0LrQvdC40LMg0L/QvtC60YPQv9C+0Log0Lgg0L/RgNC+0LTQsNC2LCDQ -sCDRgtCw0LrQttC1INGE0L7RgNC80LjRgNC+0LLQsNC90LjRjyDQvdCw0LvQvtCz0L7QstC+0Lkg -0LTQtdC60LvQsNGA0LDRhtC40Lgg0L/QviDQndCU0KEuINCU0LDQvdC90YvQvCDQv9GA0L7Qs9GA -0LDQvNC80L3Ri9C8INC/0YDQvtC00YPQutGC0L7QvCDQvNC+0LbQtdGCINCy0L7RgdC/0L7Qu9GM -0LfQvtCy0LDRgtGM0YHRjyDQu9GO0LHQvtC5INC90LDQu9C+0LPQvtC/0LvQsNGC0LXQu9GM0YnQ -uNC6INCx0LXRgdC/0LvQsNGC0L3QviDQt9Cw0LPRgNGD0LfQuNCyINC10LPQviDRgSDQvtGE0LjR -htC40LDQu9GM0L3QvtCz0L4g0YHQsNC50YLQsCDQpNCd0KEg0KDQvtGB0YHQuNC4IChodHRwOi8v -d3d3Lm5hbG9nLnJ1L3JuNzcvL3Byb2dyYW0vYWxsL25hbF91bC8pLjxicj4NCjxicj4NCtCS0LXQ -tNGD0YnQsNGPOiDQlNC80LjRgtGA0LjQuSDQodGC0LDQvdC40YHQu9Cw0LLQvtCy0LjRhywg0LXR -gdGC0Ywg0YLQsNC60LDRjyDRgdC40YLRg9Cw0YbQuNGPOiDQtNC+0LHRgNC+0YHQvtCy0LXRgdGC -0L3QsNGPINC60L7QvNC/0LDQvdC40Y8g0L7RgtGA0LDQt9C40LvQsCDQsiDQtNC10LrQu9Cw0YDQ -sNGG0LjQuCDRgNGP0LQg0YHRh9C10YLQvtCyLdGE0LDQutGC0YPRgCwg0L/QviDQutC+0YLQvtGA -0YvQvCDQv9C+0YHRgtCw0LLRidC40Log0L7RgtGH0LXRgtC90L7RgdGC0Ywg0L3QtSDRgdC00LDQ -uyDQstC+0L7QsdGJ0LUuINCl0L7RgtGPINC90LAg0LzQvtC80LXQvdGCINC/0YDQvtCy0LXQtNC1 -0L3QuNGPINGB0LTQtdC70LrQuCDQutC+0L3RgtGA0LDQs9C10L3RgiDQv9C+INC00LDQvdC90YvQ -vCDQstGL0L/QuNGB0LrQuCDQuNC3INCV0JPQoNCu0Jsg0LHRi9C7INCy0L/QvtC70L3QtSDQtNC1 -0LnRgdGC0LLRg9GO0YnQuNC8LiDQmtCw0LrQuNC1INC/0L7RgdC70LXQtNGB0YLQstC40Y8g0L7Q -ttC40LTQsNGO0YIg0L3QsNC70L7Qs9C+0L/Qu9Cw0YLQtdC70YzRidC40LrQsCDQsiDRgtCw0LrQ -vtC8INGB0LvRg9GH0LDQtT8gPHA+DQo8YnI+DQrQodCw0YLQuNC9INCULtChLjog0JXRgdC70Lgg -0LrQvtC90YLRgNCw0LPQtdC90YIg0L3QsNC70L7Qs9C+0L/Qu9Cw0YLQtdC70YzRidC40LrQsCDQ -vdC1INC/0YDQtdC00YHRgtCw0LLQuNC7INC90LDQu9C+0LPQvtCy0YPRjiDQtNC10LrQu9Cw0YDQ -sNGG0LjRjiDQv9C+INCd0JTQoSDQuNC70Lgg0LIg0LXQs9C+INC/0YDQtdC00YHRgtCw0LLQu9C1 -0L3QvdC+0Lkg0LTQtdC60LvQsNGA0LDRhtC40Lgg0L3QtSDQvtGC0YDQsNC20LXQvdGLINC60LDQ -utC40LUt0LvQuNCx0L4g0YHRh9C10YLQsC3RhNCw0LrRgtGD0YDRiywg0YLQviDRgtCw0LrQvtC5 -INC60L7QvdGC0YDQsNCz0LXQvdGCINGB0YLQsNC90L7QstC40YLRgdGPINC+0LHRitC10LrRgtC+ -0Lwg0LLQvdC40LzQsNC90LjRjyDRgdC+INGB0YLQvtGA0L7QvdGLINC90LDQu9C+0LPQvtCy0L7Q -s9C+INC+0YDQs9Cw0L3QsC4g0J3QsCDQv9C10YDQstC+0Lwg0Y3RgtCw0L/QtSDQsiDRgdC70YPR -h9Cw0LUg0L7RgtGB0YPRgtGB0YLQstC40Y8g0L3QsNC70L7Qs9C+0LLQvtC5INC00LXQutC70LDR -gNCw0YbQuNC4INC90LDQu9C+0LPQvtCy0YvQuSDQvtGA0LPQsNC9INCx0YPQtNC10YIg0LjQvNC1 -0YLRjCDQstC+0LfQvNC+0LbQvdC+0YHRgtGMINC/0YDQuNC+0YHRgtCw0L3QvtCy0LjRgtGMINC0 -0LLQuNC20LXQvdC40LUg0LTQtdC90LXQttC90YvRhSDRgdGA0LXQtNGB0YLQsiDQv9C+INGA0LDR -gdGH0LXRgtC90YvQvCDRgdGH0LXRgtCw0LwuINCU0LDQu9C10LUg0L/RgNC+0LLQvtC00LjRgtGB -0Y8g0YPRgdGC0LDQvdC+0LLQu9C10L3QvdGL0Lkg0LPQu9Cw0LLQvtC5IDE0INCd0LDQu9C+0LPQ -vtCy0L7Qs9C+INC60L7QtNC10LrRgdCwINCg0L7RgdGB0LjQudGB0LrQvtC5INCk0LXQtNC10YDQ -sNGG0LjQuCDQutC+0LzQv9C70LXQutGBINC60L7QvdGC0YDQvtC70YzQvdGL0YUg0LzQtdGA0L7Q -v9GA0LjRj9GC0LjQuSDQv9C+INGE0L7RgNC80LjRgNC+0LLQsNC90LjRjiDQtNC+0LrQsNC30LDR -gtC10LvRjNC90L7QuSDQsdCw0LfRiyDQvtCxINGD0LrQu9C+0L3QtdC90LjQuCDQvtGCINC90LDQ -u9C+0LPQvtC+0LHQu9C+0LbQtdC90LjRjy4g0K3RgtC+INC40YHRgtGA0LXQsdC+0LLQsNC90LjQ -tSDQuNC90YTQvtGA0LzQsNGG0LjQuCDQuCDQtNC+0LrRg9C80LXQvdGC0L7Qsiwg0LAg0L/RgNC4 -INC90LXQvtCx0YXQvtC00LjQvNC+0YHRgtC4INC00YDRg9Cz0LjQtSDQvNC10YDQvtC/0YDQuNGP -0YLQuNGPINC90LDQu9C+0LPQvtCy0L7Qs9C+INC60L7QvdGC0YDQvtC70Y8uINCf0YDQuCDRjdGC -0L7QvCDQsiDRgdC70YPRh9Cw0LUg0YPRgdGC0LDQvdC+0LLQu9C10L3QuNGPINGE0LDQutGC0LAg -0YDQtdCw0LvRjNC90L7RgdGC0Lgg0L7Qv9C10YDQsNGG0LjQuCwg0LTQu9GPINGB0LDQvNC+0LPQ -viDQvdCw0LvQvtCz0L7Qv9C70LDRgtC10LvRjNGJ0LjQutCwINC90Lgg0LrQsNC60LjRhSDQv9C+ -0YHQu9C10LTRgdGC0LLQuNC5INC90LUg0LHRg9C00LXRgi4g0Jog0L7RgtCy0LXRgtGB0YLQstC1 -0L3QvdC+0YHRgtC4INCx0YPQtNC10YIg0L/RgNC40LLQu9C10YfQtdC90L4g0YLQviDQu9C40YbQ -viwg0LrQvtGC0L7RgNC+0LUg0L3QsNGA0YPRiNC40LvQviDQvdCw0LvQvtCz0L7QstC+0LUg0LfQ -sNC60L7QvdC+0LTQsNGC0LXQu9GM0YHRgtCy0L4uPGJyPg0KPHA+DQrQn9GA0Lgg0Y3RgtC+0Lwg -0LzRiyDRgNC10LrQvtC80LXQvdC00YPQtdC8INCw0LrQutGD0YDQsNGC0L3QviDQv9C+0LTRhdC+ -0LTQuNGC0Ywg0Log0LLRi9Cx0L7RgNGDINC/0L7RgtC10L3RhtC40LDQu9GM0L3Ri9GFINC60L7Q -vdGC0YDQsNCz0LXQvdGC0L7QsiDQuCDQv9GA0L7Rj9Cy0LvRj9GC0Ywg0LTQvtC70LbQvdGD0Y4g -0L7RgdC80L7RgtGA0LjRgtC10LvRjNC90L7RgdGC0YwsINGC0LDQuiDQutCw0Log0Y3RgtC+INC9 -0LXQvtCx0YXQvtC00LjQvNC+INC00LvRjyDRgdC+0YXRgNCw0L3QtdC90LjRjyDQtNC10LvQvtCy -0L7QuSDRgNC10L/Rg9GC0LDRhtC40Lgg0Lgg0YTQvtGA0LzQuNGA0L7QstCw0L3QuNGPINC/0L7Q -u9C+0LbQuNGC0LXQu9GM0L3QvtC5INC90LDQu9C+0LPQvtCy0L7QuSDQuNGB0YLQvtGA0LjQuC48 -cD4NCjxicj4NCtCS0LXQtNGD0YnQsNGPOiDQldGB0LvQuCDQsiDRgdCy0LXQtNC10L3QuNGP0YUg -0YMg0LrQvtC90YLRgNCw0LPQtdC90YLQvtCyINCx0YPQtNGD0YIg0YDQsNGB0YXQvtC20LTQtdC9 -0LjRjywg0L3QsNC/0YDQuNC80LXRgCwg0YDQsNC30L3Ri9C1INC90L7QvNC10YDQsCDRgdGH0LXR -gtC+0LIt0YTQsNC60YLRg9GAINC4INGA0LDQt9C90YvQtSDQtNCw0YLRiywg0LrQsNC6INGN0YLQ -viDQsdGD0LTRg9GCINC+0YbQtdC90LjQstCw0YLRjCDQuNC90YHQv9C10LrRgtC+0YDRiz8g0JAg -0LXRgdC70Lgg0L7RgtC70LjRh9Cw0Y7RgtGB0Y8g0YHRg9C80LzRiyDQv9C+INC30LDRgNC10LPQ -uNGB0YLRgNC40YDQvtCy0LDQvdC90YvQvCDRgdGH0LXRgtCw0Lwt0YTQsNC60YLRg9GA0LDQvD8g -PGJyPg0KPGJyPg0K0KHQsNGC0LjQvSDQlC7QoS46INCf0YDQtdC20LTQtSDQstGB0LXQs9C+INCy -0L4g0LjQt9Cx0LXQttCw0L3QuNC1INGC0LXRhdC90LjRh9C10YHQutC40YUg0L7RiNC40LHQvtC6 -INCyINC/0YDQtdC00YHRgtCw0LLQu9C10L3QvdC+0Lkg0LTQtdC60LvQsNGA0LDRhtC40Lgg0L/Q -viDQndCU0KEg0LzRiyDRgNC10LrQvtC80LXQvdC00YPQtdC8INC/0YDQvtCy0LXRgNC40YLRjCDQ -uNC90YTQvtGA0LzQsNGG0LjRjiDQviDQutC+0L3RgtGA0LDQs9C10L3RgtCw0YUsINC60L7RgtC+ -0YDQsNGPINGB0L7QtNC10YDQttC40YLRgdGPINCyINCy0LDRiNC10Lkg0YPRh9C10YLQvdC+0Lkg -KNCx0YPRhdCz0LDQu9GC0LXRgNGB0LrQvtC5KSDRgdC40YHRgtC10LzQtSwg0L3QsCDQv9GA0LXQ -tNC80LXRgiDQv9GA0LDQstC40LvRjNC90L7RgdGC0Lgg0LfQsNC90LXRgdC10L3QuNGPINCyINGB -0LjRgdGC0LXQvNGDINCY0J3QnSDQuCDQmtCf0J8g0LrQvtC90YLRgNCw0LPQtdC90YLQvtCyLiDQ -nNC+0LbQvdC+INCy0L7RgdC/0L7Qu9GM0LfQvtCy0LDRgtGM0YHRjywg0L3QsNC/0YDQuNC80LXR -gCwg0L7QvdC70LDQudC9LdGB0LXRgNCy0LjRgdC+0LwsINGA0LDQt9C80LXRidC10L3QvdGL0Lwg -0L3QsCDQvtGE0LjRhtC40LDQu9GM0L3QvtC8INGB0LDQudGC0LUg0KTQndChINCg0L7RgdGB0LjQ -uCAod3d3Lm5hbG9nLnJ1LCBodHRwOi8vbnBjaGsubmFsb2cucnUpLjxicj4NCjxicj4NCtCV0YHQ -u9C4INGA0LDRgdGF0L7QttC00LXQvdC40Y8g0LIg0YHQstC10LTQtdC90LjRj9GFINC+0LEg0L7Q -v9C10YDQsNGG0LjRj9GFINC60L7QvdGC0YDQsNCz0LXQvdGC0L7QsiDQsdGD0LTRg9GCINCy0YHQ -tS3RgtCw0LrQuCDQstGL0Y/QstC70LXQvdGLLCDRgtC+INC80Ysg0LjRhSDQtNC10LvQuNC8INC9 -0LAg0LTQstC1INC60LDRgtC10LPQvtGA0LjQuC4g0J/QtdGA0LLQsNGPINGN0YLQviDRgtC10YXQ -vdC40YfQtdGB0LrQuNC1INC+0YjQuNCx0LrQuCwg0YLQsNC6INC90LDQt9GL0LLQsNC10LzRi9C1 -ICLQvtGI0LjQsdC60Lgg0LLQstC+0LTQsCIsINC60L7RgtC+0YDRi9C1INC90LUg0LjQvNC10Y7R -giDQstGL0YHQvtC60L7Qs9C+INC/0YDQuNC+0YDQuNGC0LXRgtCwINCyINC+0YLRgNCw0LHQvtGC -0LrQtS4g0J7RiNC40LHQutC4INCyINC90L7QvNC10YDQtSwg0LTQsNGC0LUg0YHRh9C10YLQsC3R -hNCw0LrRgtGD0YDRiyDQuNC70Lgg0LIg0LTRgNGD0LPQvtC8INGA0LXQutCy0LjQt9C40YLQtSwg -0L3QtSDQstC70LjRj9GO0YnQtdC8INC90LAg0YHRg9C80LzRgyDQvdCw0LvQvtCz0LAsINC80Ysg -0YDQsNGB0YHRh9C40YLRi9Cy0LDQtdC8INGD0YHRgtGA0LDQvdGP0YLRjCDQvdCwINGN0YLQsNC/ -0LUg0LfQsNC/0YDQvtGB0LAg0L/QvtGP0YHQvdC10L3QuNC5LiDQn9GA0Lgg0Y3RgtC+0Lwg0L3Q -sNC70L7Qs9C+0L/Qu9Cw0YLQtdC70YzRidC40LrRgyDQv9GA0LXQtNGB0YLQsNCy0LjRgtGB0Y8g -0LLQvtC30LzQvtC20L3QvtGB0YLRjCDQvdCw0L/RgNCw0LLQuNGC0Ywg0LIg0L3QsNC70L7Qs9C+ -0LLRi9C5INC+0YDQs9Cw0L0g0YTQvtGA0LzQsNC70LjQt9C+0LLQsNC90L3Ri9C1INC/0L7Rj9GB -0L3QtdC90LjRjyDQsdC10Lcg0LrQsNC60LjRhS3Qu9C40LHQviDQvdCw0LvQvtCz0L7QstGL0YUg -0L/QvtGB0LvQtdC00YHRgtCy0LjQuS4g0JTQu9GPINGN0YLQvtCz0L4g0L3QsNC00L4g0LHRg9C0 -0LXRgiDRg9C60LDQt9Cw0YLRjCDQsiDRgdC/0LXRhtC40LDQu9GM0L3QvtC5INGA0LXQutC+0LzQ -tdC90LTQvtCy0LDQvdC90L7QuSDRhNC+0YDQvNC1INC60L7RgNGA0LXQutGC0L3Ri9C1INGB0LLQ -tdC00LXQvdC40Y8g0Lgg0L3QsNC/0YDQsNCy0LjRgtGMINC40YUg0L/QviDQotCa0KEg0YfQtdGA -0LXQtyDQvtC/0LXRgNCw0YLQvtGA0LAg0Y3Qu9C10LrRgtGA0L7QvdC90L7Qs9C+INC00L7QutGD -0LzQtdC90YLQvtC+0LHQvtGA0L7RgtCwINCyINC90LDQu9C+0LPQvtCy0YvQtSDQvtGA0LPQsNC9 -0YsuINCf0YDQtdC00YHRgtCw0LLQu9GP0YLRjCDRg9GC0L7Rh9C90LXQvdC90YPRjiDQvdCw0LvQ -vtCz0L7QstGD0Y4g0LTQtdC60LvQsNGA0LDRhtC40Y4g0L/QviDQndCU0KEg0LIg0YLQsNC60L7Q -vCDRgdC70YPRh9Cw0LUg0L3QtSDRgtGA0LXQsdGD0LXRgtGB0Y8uPGJyPg0KPHA+DQrQldGB0LvQ -uCDQttC1INGA0LDRgdGF0L7QttC00LXQvdC40Y8g0LLRi9C30LLQsNC90Ysg0L3QtdCy0LXRgNC9 -0YvQvCDRgNCw0YHRh9C10YLQvtC8INGB0YPQvNC80Ysg0L3QsNC70L7Qs9CwINC40LvQuCDRgdGH -0LXRgi3RhNCw0LrRgtGD0YDQsCDQvtGC0YDQsNC20LXQvSDQvtGI0LjQsdC+0YfQvdC+LCDRgtC+ -INCyINGB0L7QvtGC0LLQtdGC0YHRgtCy0LjQuCDRgdC+INGB0YLQsNGC0YzQtdC5IDgxINCd0LDQ -u9C+0LPQvtCy0L7Qs9C+INC60L7QtNC10LrRgdCwINCg0L7RgdGB0LjQudGB0LrQvtC5INCk0LXQ -tNC10YDQsNGG0LjQuCDQvdC10L7QsdGF0L7QtNC40LzQviDQsdGD0LTQtdGCINC/0YDQtdC00YHR -gtCw0LLQuNGC0Ywg0YPRgtC+0YfQvdC10L3QvdGD0Y4g0L3QsNC70L7Qs9C+0LLRg9GOINC00LXQ -utC70LDRgNCw0YbQuNGOINC/0L4g0J3QlNChLiDQmCDQt9C00LXRgdGMINC/0YDQtdC00YPRgdC8 -0LDRgtGA0LjQstCw0LXRgtGB0Y8g0L3QvtCy0YvQuSDQv9C+0LTRhdC+0LQuINCi0LXQv9C10YDR -jCDQtNC+0L/Rg9GB0LrQsNC10YLRgdGPINC/0YDQtdC00YHRgtCw0LLQu9C10L3QuNC1INGD0YLQ -vtGH0L3QtdC90L3QvtC5INC90LDQu9C+0LPQvtCy0L7QuSDQtNC10LrQu9Cw0YDQsNGG0LjQuCAi -0L3QsCDQtNC10LvRjNGC0YMiLiDQotC+INC10YHRgtGMINCyINGD0YLQvtGH0L3QtdC90L3QvtC5 -INC90LDQu9C+0LPQvtCy0L7QuSDQtNC10LrQu9Cw0YDQsNGG0LjQuCDQt9Cw0L/QvtC70L3Rj9GO -0YLRgdGPINGC0L7Qu9GM0LrQviDRgtC1INGA0LDQt9C00LXQu9GLLCDQsiDQutC+0YLQvtGA0YvQ -tSDQstC90LXRgdC10L3RiyDQuNGB0L/RgNCw0LLQu9C10L3QuNGPLiDQn9C+0LTRgNC+0LHQvdC1 -0LUg0L/QvtGA0Y/QtNC+0Log0LfQsNC/0L7Qu9C90LXQvdC40Y8g0L3QsNC70L7Qs9C+0LLQvtC5 -INC00LXQutC70LDRgNCw0YbQuNC4INC40LfQu9C+0LbQtdC9INCyINC/0YDQuNC60LDQt9C1INCk -0J3QoSDQoNC+0YHRgdC40Lgg0L7RgiAyOS4xMC4yMDE0IOKEliDQnNCc0JItNy0zLzU1OEAuPGJy -Pg0KPHA+DQo8cD4NCtCd0LDQu9C+0LPQvtC/0LvQsNGC0LXQu9GM0YnQuNC60LDQvNC4INC4INC/ -0LvQsNGC0LXQu9GM0YnQuNC60LDQvNC4INGB0LHQvtGA0L7QsiDQv9GA0LjQt9C90LDRjtGC0YHR -jyDQvtGA0LPQsNC90LjQt9Cw0YbQuNC4INC4INGE0LjQt9C40YfQtdGB0LrQuNC1INC70LjRhtCw -LCDQvdCwINC60L7RgtC+0YDRi9GFINCyINGB0L7QvtGC0LLQtdGC0YHRgtCy0LjQuCDRgSDQvdCw -0YHRgtC+0Y/RidC40Lwg0JrQvtC00LXQutGB0L7QvCDQstC+0LfQu9C+0LbQtdC90LAg0L7QsdGP -0LfQsNC90L3QvtGB0YLRjCDRg9C/0LvQsNGH0LjQstCw0YLRjCDRgdC+0L7RgtCy0LXRgtGB0YLQ -stC10L3QvdC+INC90LDQu9C+0LPQuCDQuCAo0LjQu9C4KSDRgdCx0L7RgNGLLjxicj4NCtCSINC/ -0L7RgNGP0LTQutC1LCDQv9GA0LXQtNGD0YHQvNC+0YLRgNC10L3QvdC+0Lwg0L3QsNGB0YLQvtGP -0YnQuNC8INCa0L7QtNC10LrRgdC+0LwsINGE0LjQu9C40LDQu9GLINC4INC40L3Ri9C1INC+0LHQ -vtGB0L7QsdC70LXQvdC90YvQtSDQv9C+0LTRgNCw0LfQtNC10LvQtdC90LjRjyDRgNC+0YHRgdC4 -0LnRgdC60LjRhSDQvtGA0LPQsNC90LjQt9Cw0YbQuNC5INC40YHQv9C+0LvQvdGP0Y7RgiDQvtCx -0Y/Qt9Cw0L3QvdC+0YHRgtC4INGN0YLQuNGFINC+0YDQs9Cw0L3QuNC30LDRhtC40Lkg0L/QviDR -g9C/0LvQsNGC0LUg0L3QsNC70L7Qs9C+0LIg0Lgg0YHQsdC+0YDQvtCyINC/0L4g0LzQtdGB0YLR -gyDQvdCw0YXQvtC20LTQtdC90LjRjyDRjdGC0LjRhSDRhNC40LvQuNCw0LvQvtCyINC4INC40L3R -i9GFINC+0LHQvtGB0L7QsdC70LXQvdC90YvRhSDQv9C+0LTRgNCw0LfQtNC10LvQtdC90LjQuS48 -YnI+DQrQkiDRgdC70YPRh9Cw0Y/RhSwg0L/RgNC10LTRg9GB0LzQvtGC0YDQtdC90L3Ri9GFINC9 -0LDRgdGC0L7Rj9GJ0LjQvCDQmtC+0LTQtdC60YHQvtC8LCDQvdCw0LvQvtCz0L7Qv9C70LDRgtC1 -0LvRjNGJ0LjQutCw0LzQuCDQv9GA0LjQt9C90LDRjtGC0YHRjyDQuNC90L7RgdGC0YDQsNC90L3R -i9C1INGB0YLRgNGD0LrRgtGD0YDRiyDQsdC10Lcg0L7QsdGA0LDQt9C+0LLQsNC90LjRjyDRjtGA -0LjQtNC40YfQtdGB0LrQvtCz0L4g0LvQuNGG0LAuPHA+DQo8cD4NCtCh0YLQsNGC0YzRjyAyMC4g -0JLQt9Cw0LjQvNC+0LfQsNCy0LjRgdC40LzRi9C1INC70LjRhtCwPHA+DQoxLiDQktC30LDQuNC8 -0L7Qt9Cw0LLQuNGB0LjQvNGL0LzQuCDQu9C40YbQsNC80Lgg0LTQu9GPINGG0LXQu9C10Lkg0L3Q -sNC70L7Qs9C+0L7QsdC70L7QttC10L3QuNGPINC/0YDQuNC30L3QsNGO0YLRgdGPINGE0LjQt9C4 -0YfQtdGB0LrQuNC1INC70LjRhtCwINC4ICjQuNC70LgpINC+0YDQs9Cw0L3QuNC30LDRhtC40Lgs -INC+0YLQvdC+0YjQtdC90LjRjyDQvNC10LbQtNGDINC60L7RgtC+0YDRi9C80Lgg0LzQvtCz0YPR -giDQvtC60LDQt9GL0LLQsNGC0Ywg0LLQu9C40Y/QvdC40LUg0L3QsCDRg9GB0LvQvtCy0LjRjyDQ -uNC70Lgg0Y3QutC+0L3QvtC80LjRh9C10YHQutC40LUg0YDQtdC30YPQu9GM0YLQsNGC0Ysg0LjR -hSDQtNC10Y/RgtC10LvRjNC90L7RgdGC0Lgg0LjQu9C4INC00LXRj9GC0LXQu9GM0L3QvtGB0YLQ -uCDQv9GA0LXQtNGB0YLQsNCy0LvRj9C10LzRi9GFINC40LzQuCDQu9C40YYsINCwINC40LzQtdC9 -0L3Qvjo8YnI+DQoxKSDQvtC00L3QsCDQvtGA0LPQsNC90LjQt9Cw0YbQuNGPINC90LXQv9C+0YHR -gNC10LTRgdGC0LLQtdC90L3QviDQuCAo0LjQu9C4KSDQutC+0YHQstC10L3QvdC+INGD0YfQsNGB -0YLQstGD0LXRgiDQsiDQtNGA0YPQs9C+0Lkg0L7RgNCz0LDQvdC40LfQsNGG0LjQuCwg0Lgg0YHR -g9C80LzQsNGA0L3QsNGPINC00L7Qu9GPINGC0LDQutC+0LPQviDRg9GH0LDRgdGC0LjRjyDRgdC+ -0YHRgtCw0LLQu9GP0LXRgiDQsdC+0LvQtdC1IDIwINC/0YDQvtGG0LXQvdGC0L7Qsi4g0JTQvtC7 -0Y8g0LrQvtGB0LLQtdC90L3QvtCz0L4g0YPRh9Cw0YHRgtC40Y8g0L7QtNC90L7QuSDQvtGA0LPQ -sNC90LjQt9Cw0YbQuNC4INCyINC00YDRg9Cz0L7QuSDRh9C10YDQtdC3INC/0L7RgdC70LXQtNC+ -0LLQsNGC0LXQu9GM0L3QvtGB0YLRjCDQuNC90YvRhSDQvtGA0LPQsNC90LjQt9Cw0YbQuNC5INC+ -0L/RgNC10LTQtdC70Y/QtdGC0YHRjyDQsiDQstC40LTQtSDQv9GA0L7QuNC30LLQtdC00LXQvdC4 -0Y8g0LTQvtC70LXQuSDQvdC10L/QvtGB0YDQtdC00YHRgtCy0LXQvdC90L7Qs9C+INGD0YfQsNGB -0YLQuNGPINC+0YDQs9Cw0L3QuNC30LDRhtC40Lkg0Y3RgtC+0Lkg0L/QvtGB0LvQtdC00L7QstCw -0YLQtdC70YzQvdC+0YHRgtC4INC+0LTQvdCwINCyINC00YDRg9Cz0L7QuTs8YnI+DQoyKSDQvtC0 -0L3QviDRhNC40LfQuNGH0LXRgdC60L7QtSDQu9C40YbQviDQv9C+0LTRh9C40L3Rj9C10YLRgdGP -INC00YDRg9Cz0L7QvNGDINGE0LjQt9C40YfQtdGB0LrQvtC80YMg0LvQuNGG0YMg0L/QviDQtNC+ -0LvQttC90L7RgdGC0L3QvtC80YMg0L/QvtC70L7QttC10L3QuNGOOzxicj4NCjMpINC70LjRhtCw -INGB0L7RgdGC0L7Rj9GCINCyINGB0L7QvtGC0LLQtdGC0YHRgtCy0LjQuCDRgSDRgdC10LzQtdC5 -0L3Ri9C8INC30LDQutC+0L3QvtC00LDRgtC10LvRjNGB0YLQstC+0Lwg0KDQvtGB0YHQuNC50YHQ -utC+0Lkg0KTQtdC00LXRgNCw0YbQuNC4INCyINCx0YDQsNGH0L3Ri9GFINC+0YLQvdC+0YjQtdC9 -0LjRj9GFLCDQvtGC0L3QvtGI0LXQvdC40Y/RhSDRgNC+0LTRgdGC0LLQsCDQuNC70Lgg0YHQstC+ -0LnRgdGC0LLQsCwg0YPRgdGL0L3QvtCy0LjRgtC10LvRjyDQuCDRg9GB0YvQvdC+0LLQu9C10L3Q -vdC+0LPQviwg0LAg0YLQsNC60LbQtSDQv9C+0L/QtdGH0LjRgtC10LvRjyDQuCDQvtC/0LXQutCw -0LXQvNC+0LPQvi48cD4NCjIuINCh0YPQtCDQvNC+0LbQtdGCINC/0YDQuNC30L3QsNGC0Ywg0LvQ -uNGG0LAg0LLQt9Cw0LjQvNC+0LfQsNCy0LjRgdC40LzRi9C80Lgg0L/QviDQuNC90YvQvCDQvtGB -0L3QvtCy0LDQvdC40Y/QvCwg0L3QtSDQv9GA0LXQtNGD0YHQvNC+0YLRgNC10L3QvdGL0Lwg0L/R -g9C90LrRgtC+0LwgMSDQvdCw0YHRgtC+0Y/RidC10Lkg0YHRgtCw0YLRjNC4LCDQtdGB0LvQuCDQ -vtGC0L3QvtGI0LXQvdC40Y8g0LzQtdC20LTRgyDRjdGC0LjQvNC4INC70LjRhtCw0LzQuCDQvNC+ -0LPRg9GCINC/0L7QstC70LjRj9GC0Ywg0L3QsCDRgNC10LfRg9C70YzRgtCw0YLRiyDRgdC00LXQ -u9C+0Log0L/QviDRgNC10LDQu9C40LfQsNGG0LjQuCDRgtC+0LLQsNGA0L7QsiAo0YDQsNCx0L7R -giwg0YPRgdC70YPQsykuPGJyPg0KPGJyPg0KPGJyPg0K0J3QtdC00LDQstC90L4gwqvRhtC40YTR -gNC+0LLQsNGPINGN0LrQvtC90L7QvNC40LrQsMK7INC+0LTQtdGA0LbQsNC70LAg0LLQsNC20L3R -g9GOINC/0L7QsdC10LTRgywg0LLRi9C60LjQvdGD0LIg0LjQtyDQv9GP0YLQtdGA0LrQuCDRgdCw -0LzRi9GFINC00L7RgNC+0LPQuNGFINC60L7QvNC/0LDQvdC40Lkg0LzQuNGA0LAg0L/QvtGB0LvQ -tdC00L3QtdCz0L4g0L/RgNC10LTRgdGC0LDQstC40YLQtdC70Y8gwqvRgNC10LDQu9GM0L3QvtCz -0L4g0YHQtdC60YLQvtGA0LDCuyBFeHhvbk1vYmlsLiDQndC+INC/0L7QutCwINCx0LjRgtCy0LAg -wqvRgdC10YDQstC10YDQsCDRgdC+INGB0YLQsNC90LrQvtC8wrsg0L/RgNC40LLQvtC00LjRgiDQ -uiDRgtC+0YDQvNC+0LbQtdC90LjRjiDRjdC60L7QvdC+0LzQuNGH0LXRgdC60L7Qs9C+INGA0L7R -gdGC0LAuINCe0YfQtdCy0LjQtNC90L4sINGH0YLQviDQtNC70Y8g0L7QutC+0L3Rh9Cw0YLQtdC7 -0YzQvdC+0LPQviDRhNC+0YDQvNC40YDQvtCy0LDQvdC40Y8g0L3QvtCy0L7Qs9C+INGN0LrQvtC9 -0L7QvNC40YfQtdGB0LrQvtCz0L4g0YPQutC70LDQtNCwINC80LjRgNGDINC/0YDQuNC00LXRgtGB -0Y8g0L/QtdGA0LXQttC40YLRjCDQtdGJ0LUg0L3QtSDQvtC00L3QviDQv9C+0YLRgNGP0YHQtdC9 -0LjQtS48cD4NCiA8YnI+DQo8cD4NCjxwPg0KPHA+DQog0J/Rj9GC0LXRgNC60YMg0LrRgNGD0L/Q -vdC10LnRiNC40YUg0L/QviDRgNGL0L3QvtGH0L3QvtC5INGB0YLQvtC40LzQvtGB0YLQuCDQutC+ -0LzQv9Cw0L3QuNC5INC+0LrQutGD0L/QuNGA0L7QstCw0LvQuCBJVC3Qs9C40LPQsNC90YLRizxi -cj4NCtCd0LXRhNGC0Y/QvdC40LrQvtCyINGB0LzQtdC90LjQu9C4INGC0LXRhdC90L7Qu9C+0LPQ -uNC4PGJyPg0K0J3QsCDRgdC80LXQvdGDINGA0LXRgdGD0YDRgdC90L7QuSDRjdC60L7QvdC+0LzQ -uNC60LUg0L/RgNC40YXQvtC00LjRgiDRgtC10YXQvdC+0LvQvtCz0LjRh9C10YHQutCw0Y8uINCV -0YHQu9C4INGA0LDQvdGM0YjQtSDQsiDRgtC+0L8tNSDQu9C40LTQtdGA0L7QsiDQv9C+INC60LDQ -v9C40YLQsNC70LjQt9Cw0YbQuNC4IElULdCz0LjQs9Cw0L3RgtGLINC/0L7Qv9Cw0LTQsNC70Lgg -0LvQuNGI0Ywg0LjQt9GA0LXQtNC60LAsINGC0L4g0YLQtdC/0LXRgNGMINCy0YHRji4uLiDihpI8 -YnI+DQrQndC+INC90Lgg0LIg0L7QtNC90L7QvCDQsdCw0L3QutC+0LzQsNGC0LUg0YHQvdGP0YLR -jCDQtNC10L3QtdCzINC90LUg0L/QvtC70YPRh9C40LvQvtGB0YwuINCi0LXQu9C10YTQvtC9INCx -0LDQvdC60LAg0L3QtSDQvtGC0LLQtdGH0LDQuywg0YHQsNC50YIg0LLQuNGB0LXQuy4g0KfQtdGA -0LXQtyDQv9C+0LvRh9Cw0YHQsCDQstGL0Y/RgdC90LjQu9C+0YHRjCwg0YfRgtC+INCx0LDQvdC6 -0L7QstGB0LrQuNC1INGB0LjRgdGC0LXQvNGLINGA0YPRhdC90YPQu9C4LCDQsCDRgdGH0LXRgtCw -INC00LXRgdGP0YLQutC+0LIg0LzQuNC70LvQuNC+0L3QvtCyINCy0LrQu9Cw0LTRh9C40LrQvtCy -INC+0LHQvdGD0LvQtdC90YsuINCU0L7Qu9C70LDRgCwg0YTRg9C90YIg0Lgg0LXQstGA0L4g0L/R -gNC10LLRgNCw0YLQuNC70LjRgdGMINCyINC/0YvQu9GMLCDQt9Cw0YLQviDRgtC1LCDQutGC0L4g -0LfQsNC/0LDRgdCw0LvRgdGPINC30L7Qu9C+0YLQvtC8INC4INC/0L7QutGD0L/QsNC7INC60YDQ -uNC/0YLQvtCy0LDQu9GO0YLRiywg0L/QvtGC0LjRgNCw0LvQuCDRgNGD0LrQuC4g0KHRgtGA0LDR -hSDQuCDRgNCw0YHRgtC10YDRj9C90L3QvtGB0YLRjCDigJQg0LLQvtGCINC00LLQsCDQs9C70LDQ -stC90YvRhSDRgdC70L7QstCwLCDQutC+0YLQvtGA0YvQtSDQsdGL0LvQuCDQsiDQt9Cw0LPQvtC7 -0L7QstC60LDRhSDQvdC+0LLQvtGB0YLQvdGL0YUg0YHQvtC+0LHRidC10L3QuNC5INCy0YHQtdGF -INC40L3RhNC+0YDQvNCw0LPQtdC90YLRgdGC0LIuINCd0L7QstGL0Lkg0LTQuNCy0L3Ri9C5INC8 -0LjRgCDQstGB0YLRgNC10YfQsNC7INGB0LLQvtC40YUg0LjRgdC/0YPQs9Cw0L3QvdGL0YUg0L7Q -sdC40YLQsNGC0LXQu9C10LnigKY8cD4NCjxicj4NCtCa0L7QvdC10YfQvdC+LCDQstC10YHRjNC8 -0LAg0LLQtdGA0L7Rj9GC0L3Qviwg0YfRgtC+INGB0YbQtdC90LDRgNC40LkgwqvRhNC40LvRjNC8 -0LAt0LrQsNGC0LDRgdGC0YDQvtGE0YvCuyDQsiDQttC40LfQvdC4INC90LjQutC+0LPQtNCwINC9 -0LUg0LHRg9C00LXRgiDRgNC10LDQu9C40LfQvtCy0LDQvS4g0J3QviDQstC+0YIg0YfRgtC+INC9 -0LDQtNC+INGH0LXRgtC60L4g0L/QvtC90LjQvNCw0YLRjDog0L3QvtCy0YvQuSDQvNC40YAsINC9 -0L7QstCw0Y8g0YbQuNGE0YDQvtCy0LDRjyDRgNC10LDQu9GM0L3QvtGB0YLRjCDRg9C20LUg0L/R -gNC40LHQuNGA0LDQtdGCINC6INGA0YPQutCw0Lwg0L7QutGA0YPQttCw0Y7RidC40Lkg0LzQuNGA -Ljxicj4NCjxwPg0K0J3QtdC00LDQstC90L4g0LLQv9C10YDQstGL0LUg0LIg0LjRgdGC0L7RgNC4 -0Lgg0L/Rj9GC0LXRgNC60LAg0YHQsNC80YvRhSDQtNC+0YDQvtCz0LjRhSDQutC+0LzQv9Cw0L3Q -uNC5INC80LjRgNCwINGB0YLQsNC70LAg0LjRgdC60LvRjtGH0LjRgtC10LvRjNC90L4gwqvRhtC4 -0YTRgNC+0LLQvtC5wrsuINCf0L7RgdC70LXQtNC90LjQuSDQv9GA0LXQtNGB0YLQsNCy0LjRgtC1 -0LvRjCDCq9GB0YLQsNGA0L7Qs9C+INC80LjRgNCwwrsg4oCUINC90LXRhNGC0Y/QvdC+0Lkg0LPQ -uNCz0LDQvdGCIEV4eG9uTW9iaWwg0LHRi9C7INCy0YvRgtC10YHQvdC10L0g0YEg0L/Rj9GC0L7Q -s9C+INC80LXRgdGC0LAg0LjQvdGC0LXRgNC90LXRgi3QvNCw0LPQsNC30LjQvdC+0LwgQW1hem9u -INC4INGB0L7RhtGB0LXRgtGM0Y4gRmFjZWJvb2suINCf0LXRgNCy0YvQtSDRgtGA0Lgg0L/QvtC3 -0LjRhtC40Lgg0L/RgNC40L3QsNC00LvQtdC20LDRgiBBcHBsZSwgQWxwaGFiZXQgKNC80LDRgtC1 -0YDQuNC90YHQutCw0Y8g0LrQvtC80L/QsNC90LjRjyBHb29nbGUpINC4IE1pY3Jvc29mdC4gwqvQ -r9Cx0LvQvtGH0L3Ri9C5wrsg0LvQuNC00LXRgCDRgdGC0L7QuNGCINC+0LrQvtC70L4gJDU3MCDQ -vNC70YDQtC48YnI+DQo8cD4NCtCf0YDQtdC40LzRg9GJ0LXRgdGC0LLQviBJVC3RgdC10LrRgtC+ -0YDQsCDQvdCw0YDQsNGB0YLQsNC10YIg0YEg0LrQvtC90YbQsCDQtNC10LLRj9C90L7RgdGC0YvR -hSDQs9C+0LTQvtCyINC/0YDQvtGI0LvQvtCz0L4g0LLQtdC60LAuINCi0L7Qs9C00LAg0L/RgNC+ -0LjQt9C+0YjQtdC7INGE0LDQu9GM0YHRgtCw0YDRgiwg0LLRi9C70LjQstGI0LjQudGB0Y8g0LIg -0LrRgNC40LfQuNGBINC00L7RgtC60L7QvNC+0LIsINGH0YPRgtGMINCx0YvQu9C+INC90LUg0L/Q -vtCz0YDRg9C30LjQstGI0LjQuSDQsNC80LXRgNC40LrQsNC90YHQutGD0Y4g0Y3QutC+0L3QvtC8 -0LjQutGDINCyINGA0LXRhtC10YHRgdC40Y4g0LIg0L3QsNGH0LDQu9C1IDIwMDAt0YUg0LPQvtC0 -0L7Qsi4g0J3QviDQuCDRgdC10LnRh9Cw0YEg0L3QvtCy0LDRjyDRhtC40YTRgNC+0LLQsNGPINGN -0YDQsCDQvdC40LrQsNC6INC90LUg0LLRi9Cy0LXQtNC10YIg0Y3QutC+0L3QvtC80LjQutGDINC9 -0LAg0YLRgNCw0LXQutGC0L7RgNC40Y4g0YPRgdGC0L7QudGH0LjQstC+0LPQviDRgNC+0YHRgtCw -LjxwPg0KPHA+DQrQkdC+0LvQtdC1INGC0L7Qs9C+LCDRgdGA0LXQtNC90LjQtSDRgtC10LzQv9GL -INGA0L7RgdGC0LAg0JLQktCfINCh0L7QtdC00LjQvdC10L3QvdGL0YUg0KjRgtCw0YLQvtCyICjQ -uNC80LXQvdC90L4g0LIg0Y3RgtC+0Lkg0YHRgtGA0LDQvdC1INCx0LDQt9C40YDRg9C10YLRgdGP -INCx0L7Qu9GM0YjQuNC90YHRgtCy0L4g0LrRgNGD0L/QvdC10LnRiNC40YUg0LLRi9GB0L7QutC+ -0YLQtdGF0L3QvtC70L7Qs9C40YfQvdGL0YUg0LrQvtGA0L/QvtGA0LDRhtC40LkpINCyIFhYSSDQ -stC10LrQtSDQvdCw0YXQvtC00Y/RgtGB0Y8g0L3QsCDQvNC40L3QuNC80LDQu9GM0L3QvtC8INGD -0YDQvtCy0L3QtSDQv9C+INGB0YDQsNCy0L3QtdC90LjRjiDRgdC+INCy0YLQvtGA0L7QuSDQv9C+ -0LvQvtCy0LjQvdC+0LkgWFgg0LLQtdC60LAuPHA+DQo8cD4NCtCSIDIwMDHigJMyMDE1INCz0L7Q -tNCw0YUg0LDQvNC10YDQuNC60LDQvdGB0LrQsNGPINGN0LrQvtC90L7QvNC40LrQsCDRgNC+0YHQ -u9CwINC90LAgMSw4JSDQsiDRgdGA0LXQtNC90LXQvCDQt9CwINCz0L7QtC4g0KDQvtGB0YIg0LIg -0L/RgNC10LTRi9C00YPRidC40LUg0LTQstC1INC/0Y/RgtC90LDQtNGG0LDRgtC40LvQtdGC0LrQ -uCDRgdC+0YHRgtCw0LLQu9GP0LsgMyw0INC4IDMsMyUsINCwINC00L4g0Y3RgtC+0LPQviDQsdGL -0Lsg0LXRidC1INCy0YvRiNC1ICjQt9C00LXRgdGMINC4INC00LDQu9C10LUg4oCUINC00LDQvdC9 -0YvQtSDQktGB0LXQvNC40YDQvdC+0LPQviDQsdCw0L3QutCwKS48YnI+DQo8cD4NCtCYINGN0YLQ -viDQvdC1INCy0YHQtSDQsNC90YLQuNGA0LXQutC+0YDQtNGLLiDQotC10LzQv9GLINGA0L7RgdGC -0LAg0LfQsCDQv9C+0YHQu9C10LTQvdC40LUg0L/Rj9GC0L3QsNC00YbQsNGC0Ywg0LvQtdGCINC9 -0Lgg0YDQsNC30YMg0L3QtSDQv9GA0LXQstGL0YjQsNC70LggNCUgKNC80LDQutGB0LjQvNGD0Lwg -4oCUIDMsOCUg4oCUINCx0YvQuyDQv9C+0LrQsNC30LDQvSDQsiAyMDA0INCz0L7QtNGDKSwg0YLQ -vtCz0LTQsCDQutCw0Log0YDQsNC90LXQtSDRjdGC0LggNCUg0LHRi9C70Lgg0L7QsdGL0YfQvdGL -0Lwg0LTQtdC70L7QvCAo0L/QuNC6INCyIDcsMjYlINCx0YvQuyDQv9C+0LrQsNC30LDQvSDQsiAx -OTg0INCz0L7QtNGDKS48cD4NCjxwPg0KPHA+DQrQk9C70YPQsdC40L3QsCDQv9Cw0LTQtdC90LjR -jyDRjdC60L7QvdC+0LzQuNC60Lgg0LIgMjAwOSDQs9C+0LTRgyAo4oCTMiw3OCUpINGB0YLQsNC7 -0LAg0LzQsNC60YHQuNC80LDQu9GM0L3QvtC5INGBIDE5NjEg0LPQvtC00LAuINCf0YDQuCDRjdGC -0L7QvCDQvNCw0YHRiNGC0LDQsdGLIMKr0L7RgtGB0LrQvtC60LDCuyDQv9C+0YHQu9C1INGB0L/Q -sNC00LAgKCsyLDUzJSDQsiAyMDEwINCz0L7QtNGDKSDQsdGL0LvQuCDQvNC40L3QuNC80LDQu9GM -0L3Ri9C80Lgg0LfQsCDQstC10YHRjCDQvdCw0LHQu9GO0LTQsNC10LzRi9C5INC/0LXRgNC40L7Q -tC4g0JIg0L7QsdGJ0LXQvCwg0L3QtSDQt9GA0Y8g0L/QvtGB0LvQtdC00L3QuNC5INC60YDQuNC3 -0LjRgSDQv9C+0LvRg9GH0LjQuyDQsiDQqNGC0LDRgtCw0YUg0L3QsNC30LLQsNC90LjQtSDCq9CS -0LXQu9C40LrQsNGPINGA0LXRhtC10YHRgdC40Y/CuyAoR3JlYXQgUmVjZXNzaW9uKS48cD4NCjxi -cj4NCiDQm9Cw0LfQtdGA0Ysg0Lgg0LTRgNC+0L3RiyDQvtGCIEZhY2Vib29rINC4INC00YDRg9Cz -0LjQtSDRgdC/0L7RgdC+0LHRiyDQvtCx0LXRgdC/0LXRh9C40YLRjCDQsdC10LTQvdGL0LUg0YHR -gtGA0LDQvdGLINC40L3RgtC10YDQvdC10YLQvtC8PGJyPg0K0JvQsNC30LXRgNGLINC90LAg0LHQ -tdC00L3QvtGB0YLRjDxicj4NCtCW0LXQu9Cw0L3QuNC1INCc0LDRgNC60LAg0KbRg9C60LXRgNCx -0LXRgNCz0LAg0L/QvtC60YDRi9GC0Ywg0LjQvdGC0LXRgNC90LXRgtC+0Lwg0LLQtdGB0Ywg0LzQ -uNGAINC90LDQsdC40YDQsNC10YIg0L3QvtCy0YvQtSDQvtCx0L7RgNC+0YLRiyDigJQg0Log0LTR -gNC+0L3QsNC8LCDQutC+0YLQvtGA0YvQtSDQsdGD0LTRg9GCINC+0LHQtdGB0L/QtdGH0LjQstCw -0YLRjCDRgdC10YLRjCDQsiDRgtGA0YPQtNC90L7QtNC+0YHRgtGD0L/QvdGL0YUuLi4g4oaSPHA+ -DQrQn9GA0LXQt9C40LTQtdC90YLRgdGC0LLQviDQkdCw0YDQsNC60LAg0J7QsdCw0LzRiyDQvNC+ -0LbQvdC+INCy0L7QvtCx0YnQtSDRgdGH0LjRgtCw0YLRjCDRgdCw0LzRi9C8INC90LXRg9C00LDR -h9C90YvQvCDRgSDRgtC+0YfQutC4INC30YDQtdC90LjRjyDRjdC60L7QvdC+0LzQuNGH0LXRgdC6 -0LjRhSDRg9GB0L/QtdGF0L7Qsi4g0JfQsCDQv9GA0LXQtNGL0LTRg9GJ0LjQtSDRgdC10LzRjCDQ -u9C10YIg0JLQktCfINCh0KjQkCDRg9Cy0LXQu9C40YfQuNCy0LDQu9GB0Y8g0YHRgNC10LTQvdC1 -0LPQvtC00L7QstGL0LzQuCDRgtC10LzQv9Cw0LzQuCAxLDQlLiDQndC4INC/0YDQuCDQvtC00L3Q -vtC8INC/0YDQtdC30LjQtNC10L3RgtC1LCDQvdCw0YfQuNC90LDRjyDRgSDQlNC20L7QvdCwINCa -0LXQvdC90LXQtNC4LCDRgtCw0Log0LzQtdC00LvQtdC90L3QviDRjdC60L7QvdC+0LzQuNC60LAg -0L3QtSDRgNC+0YHQu9CwLjxwPg0KPGJyPg0K0KLQtdC60YPRidC40Lkg0LPQvtC0INC90LUg0L/R -gNC40L3QtdGB0LXRgiDQvdC40YfQtdCz0L4g0YXQvtGA0L7RiNC10LPQvi4g0JIg0L/QtdGA0LLQ -vtC8INC60LLQsNGA0YLQsNC70LUg0JLQktCfINCy0YvRgNC+0YEg0L3QsCAxLDElINCyINCz0L7Q -tNC+0LLQvtC8INC40YHRh9C40YHQu9C10L3QuNC4LCDQstC+INCy0YLQvtGA0L7QvCwg0L/QviDQ -v9C10YDQstC+0Lkg0L7RhtC10L3QutC1LCDQvdCwIDEsMiUuINCf0YDQvtCz0L3QvtC3INC90LAg -0LLQtdGB0Ywg0LPQvtC0IOKAlCAy4oCTMiwyJSwg0YfRgtC+INCx0YPQtNC10YIg0LzQtdC90YzR -iNC1INC/0YDQvtGI0LvQvtCz0L7QtNC90LjRhSAyLDQlLjxwPg0KPHA+DQrQp9C70LXQvSDRgdC+ -0LLQtdGC0LAg0YPQv9GA0LDQstC70Y/RjtGJ0LjRhSDQpNC10LTQtdGA0LDQu9GM0L3QvtC5INGA -0LXQt9C10YDQstC90L7QuSDRgdC40YHRgtC10LzRiyDQodCo0JAg0JTQttC10YDQvtC8INCf0LDR -g9GN0LvQuyDQsiDQuNC90YLQtdGA0LLRjNGOIEZpbmFuY2lhbCBUaW1lcyDQt9Cw0Y/QstC40Lss -INGH0YLQviDQtdGB0YLRjCDRgNC40YHQuiDQstGC0Y/Qs9C40LLQsNC90LjRjyDQsiDQtNC70LjR -gtC10LvRjNC90YvQuSDQv9C10YDQuNC+0LQg0YHQu9Cw0LHQvtCz0L4g0YDQvtGB0YLQsC48YnI+ -DQo8cD4NCtCd0LDQtNC+INGC0LDQutC20LUg0YPRh9C40YLRi9Cy0LDRgtGMLCDRh9GC0L4g0Y3R -gtC+0YIg0LzQuNC90LjQvNCw0LvRjNC90YvQuSDRgNC+0YHRgiDQv9C+0YHQu9C10LTQvdC40YUg -0LvQtdGCINGB0L7Qv9GA0L7QstC+0LbQtNCw0LXRgtGB0Y8g0YPQstC10LvQuNGH0LXQvdC40LXQ -vCDQtNC+0LvQs9CwLiDQk9C+0YHRg9C00LDRgNGB0YLQstC10L3QvdGL0Lkg0LTQvtC70LMg0LLR -i9GA0L7RgSDQt9CwINCy0L7RgdC10LzRjCDQu9C10YIg0L/QvtGH0YLQuCDQsiDQtNCy0LAg0YDQ -sNC30LAg0Lgg0YHQtdC50YfQsNGBINC/0YDQtdCy0YvRiNCw0LXRgiAxMDAlINCS0JLQnyDQodCo -0JAg0Lgg0YHQvtGB0YLQsNCy0LvRj9C10YIgJDE5LDQg0YLRgNC70L0uINCSINGN0YLQvtC8INCz -0L7QtNGDLCDQv9C+INC+0YbQtdC90LrQtSDQsNC80LXRgNC40LrQsNC90YHQutC+0LPQviDQvNC4 -0L3RhNC40L3QsCwg0L7QvSDQstGL0YDQsNGB0YLQtdGCINC10YnQtSDQvdCwICQzODMg0LzQu9GA -0LQuPGJyPg0KPGJyPg0K0J7QtNC90L7QstGA0LXQvNC10L3QvdC+INCk0KDQoSDRg9C00LXRgNC2 -0LjQstCw0LXRgiDQutC70Y7Rh9C10LLRg9GOINGB0YLQsNCy0LrRgyDQvdCwINC80LjQvdC40LzQ -sNC70YzQvdC+0Lwg0YPRgNC+0LLQvdC1INC90LjQttC1IDElINGBINC00LXQutCw0LHRgNGPIDIw -MDgg0LPQvtC00LAuINCX0LAg0Y3RgtC+INCy0YDQtdC80Y8g0LHRi9C70L4g0YDQtdCw0LvQuNC3 -0L7QstCw0L3QviDRgtGA0Lgg0YDQsNGD0L3QtNCwINC/0YDQvtCz0YDQsNC80LzRiyDQutC+0LvQ -uNGH0LXRgdGC0LLQtdC90L3QvtCz0L4g0YHQvNGP0LPRh9C10L3QuNGPIChRRSksINC60L7RgtC+ -0YDQsNGPINC30LDQstC10YDRiNC40LvQsNGB0Ywg0LIg0L7QutGC0Y/QsdGA0LUgMjAxNCDQs9C+ -0LTQsCAo0LIg0YLRgNC10YLRjNC10Lwg0YDQsNGD0L3QtNC1INCyINC80LXRgdGP0YYg0KTQoNCh -INC/0L7QutGD0L/QsNC7INGDINCx0LDQvdC60L7QsiDQs9C+0YHRg9C00LDRgNGB0YLQstC10L3Q -vdGL0YUg0Lgg0LjQv9C+0YLQtdGH0L3Ri9GFINC+0LHQu9C40LPQsNGG0LjQuSDQvdCwICQ4NSDQ -vNC70YDQtCkuPGJyPg0KPHA+DQrQndC+LCDQv9C+0LTRh9C10YDQutC90LXQvCDQtdGJ0LUg0YDQ -sNC3LCDQvdC10YHQvNC+0YLRgNGPINC90LAg0LLRgdC1INGN0YLQuCDRjdC60YHRgtGA0LDQvtGA -0LTQuNC90LDRgNC90YvQtSDQvNC10YDRiywg0YLQtdC80L/RiyDRgNC+0YHRgtCwINC/0YDQtdCx -0YvQstCw0Y7RgiDQvdCwINC80L3QvtCz0L7Qu9C10YLQvdC40YUg0LzQuNC90LjQvNGD0LzQsNGF -LCDQsCDQstGB0Y8g0Y3RgtCwINC40YHRgtC+0YDQuNGPINCy0LXQu9C40LrQvtCz0L4g0YLQvtGA -0LzQvtC20LXQvdC40Y8g0L/RgNC+0LjRgdGF0L7QtNC40YIg0L3QsCDRhNC+0L3QtSDRgNC10LfQ -utC+0LPQviDRg9GB0LjQu9C10L3QuNGPINGA0L7Qu9C4IElULdGB0LXQutGC0L7RgNCwLCDQsCDR -gtCw0LrQttC1INGA0L7RgdGC0LAg0YTQuNC90LDQvdGB0L7QstGL0YUg0YDRi9C90LrQvtCyLjxw -Pg0KPHA+DQrQmtC70Y7Rh9C10LLQvtC5INCx0LjRgNC20LXQstC+0Lkg0LjQvdC00LXQutGBIFMm -UDUwMCDQvdCw0YXQvtC00LjRgtGB0Y8g0L3QsCDQuNGB0YLQvtGA0LjRh9C10YHQutC40YUg0LzQ -sNC60YHQuNC80YPQvNCw0YUuINCQ0L3QsNC70LjRgtC40LrQuCBHb2xkbWFuIFNhY2hzINC/0YDQ -tdC00YPQv9GA0LXQttC00LDRjtGCOiDQutC+0L3QtdGGINGA0LDQu9C70Lgg0LHQu9C40LfQvtC6 -LiDQn9GA0LXQtNGL0LTRg9GJ0LjQtSDQv9C10YDQuNC+0LTRiyDRgNC+0YHRgtCwICjQsiAxOTg0 -4oCTMTk4NyDQuCAxOTk04oCTMTk5OSDQs9C+0LTQsNGFKSDQt9Cw0LrQsNC90YfQuNCy0LDQu9C4 -0YHRjCDQvtCx0LLQsNC70L7QvCDQutC+0YLQuNGA0L7QstC+0LouPHA+DQo8cD4NCtCi0L4sINGH -0YLQviDQv9GA0L7QuNGB0YXQvtC00LjRgiDQsiDQodCo0JAsINCyINGC0L7QuSDQuNC70Lgg0LjQ -vdC+0Lkg0YHRgtC10L/QtdC90Lgg0YXQsNGA0LDQutGC0LXRgNC90L4g0Lgg0LTQu9GPINC00YDR -g9Cz0LjRhSDRgNCw0LfQstC40YLRi9GFINGB0YLRgNCw0L06INCy0LDQuyDQtNC+0LvQs9C+0LIs -INC90LjQt9C60LjQtSDRgtC10LzQv9GLINGA0L7RgdGC0LAsINC+0YLRgdGD0YLRgdGC0LLQuNC1 -INC40L3RhNC70Y/RhtC40LgsINC/0L7RgdGC0LXQv9C10L3QvdC+0LUg0YHQvtC60YDQsNGJ0LXQ -vdC40LUg0YHRgNC10LTQvdC10LPQviDQutC70LDRgdGB0LAg0Lgg0LrQvtC90YbQtdC90YLRgNCw -0YbQuNGPINCx0L7Qs9Cw0YLRgdGC0LLQsCDQsiDRgNGD0LrQsNGFINC+0LPRgNCw0L3QuNGH0LXQ -vdC90L7Qs9C+INC60YDRg9Cz0LAg0LvRjtC00LXQuS4g0J/RgNC4INGN0YLQvtC8INC40LfQvNC1 -0L3QtdC90LjQtSDRgdC40YLRg9Cw0YbQuNC4INGBINC/0L7QvNC+0YnRjNGOINC80LXRgCDRjdC6 -0L7QvdC+0LzQuNGH0LXRgdC60L7QuSDQuCDQtNC10L3QtdC20L3Qvi3QutGA0LXQtNC40YLQvdC+ -0Lkg0L/QvtC70LjRgtC40LrQuCDQvdC10LLQvtC30LzQvtC20L3Qvi4g0K3RgtC+INC90LUg0YHR -h9C40YLQsNGPIMKr0YfQtdGA0L3Ri9GFINC70LXQsdC10LTQtdC5wrsg0LLRgNC+0LTQtSBCcmV4 -aXQsINC60L7RgtC+0YDRi9C1INGB0LXRjtGCINGB0LzRj9GC0LXQvdC40LUg0Lgg0YXQsNC+0YEg -0L3QsCDRgNGL0L3QutCw0YUuPHA+DQo8YnI+DQrQlNC+0LvQs9C+0LUg0LLRgNC10LzRjyDQvNC4 -0YAg0LLRi9C/0LvRi9Cy0LDQuyDQt9CwINGB0YfQtdGCINCx0YPRgNC90L7Qs9C+INGA0L7RgdGC -0LAg0LIg0YHRgtGA0LDQvdCw0YUg0YLRgNC10YLRjNC10LPQviDQvNC40YDQsCwg0LrQvtGC0L7R -gNGL0LUg0Y3QutGB0L/QvtGA0YLQuNGA0L7QstCw0LvQuCDRgdGL0YDRjNC1INC/0L4g0LLRi9GB -0L7QutC40Lwg0YbQtdC90LDQvCwg0L/QvtC60YPQv9Cw0LvQuCDRgtC+0LLQsNGA0Ysg0Lgg0YLQ -tdGF0L3QvtC70L7Qs9C40Lgg0Lgg0YDQsNC30YDQtdGI0LDQu9C4INC+0YLQutGA0YvQstCw0YLR -jCDRgyDRgdC10LHRjyDQv9GA0L7QuNC30LLQvtC00YHRgtCy0LAg0YLRgNCw0L3RgdC90LDRhtC4 -0L7QvdCw0LvRjNC90YvQvCDQutC+0YDQv9C+0YDQsNGG0LjRj9C8LCDRgdC90LDQsdC20LDRjyDQ -uNGFINC00LXRiNC10LLQvtC5INGA0LDQsdC+0YfQtdC5INGB0LjQu9C+0LkuINCd0L4g0YHQtdCz -0L7QtNC90Y8g0L7QvdC4INGC0LDQutC20LUg0LIg0LrRgNC40LfQuNGB0LUuPGJyPg0KPGJyPg0K -INCV0LvQuNC30LDQstC10YLQsCDQkNC70LXQutGB0LDQvdC00YDQvtCy0LAt0JfQvtGA0LjQvdCw -INC+INGC0L7QvCwg0LPQvtGC0L7QstC+INC70Lgg0YfQtdC70L7QstC10YfQtdGB0YLQstC+INC6 -INCz0LXQvdC10YLQuNGH0LXRgdC60L7QuSDQuCDRgtC10YXQvdC+0LvQvtCz0LjRh9C10YHQutC+ -0LkgwqvRgNC10LTQsNC60YLRg9GA0LXCuzxicj4NCtCn0LXQu9C+0LLQtdC6INC90L7QstGL0Lks -INGD0LvRg9GH0YjQtdC90L3Ri9C5PHA+DQrQniDQvdC+0LLQvtC8INGH0LXQu9C+0LLQtdC60LUs -IGwnaG9tbWUgbm91dmVhdSwg0LzQtdGH0YLQsNC70Lgg0YHQtdCy0LXRgNC+0LDQvNC10YDQuNC6 -0LDQvdGB0LrQuNC1INC/0L7RgdC10LvQtdC90YbRiywg0L3QsNGG0LjRgdGC0Ysg0Lgg0LrQvtC8 -0LzRg9C90LjRgdGC0YssINCi0YDQvtGG0LrQuNC5LCDQp9C1INCT0LXQstCw0YDQsCDQuCDQvNC9 -0L7Qs9C40LUg0LTRgNGD0LPQuNC1LiDQoNC10YfRjCDRiNC70LAg0L7QsS4uLiDihpI8YnI+DQrQ -otCw0Log0L/QvtGH0LXQvNGDINC20LUgwqvRhtC40YTRgNCwwrsg0YLQsNC6INC4INC90LUg0YHR -gtCw0LvQsCDRgtC10Lwg0YHQsNC80YvQvCDQtNGA0LDQudCy0LXRgNC+0LwsINC60L7RgtC+0YDR -i9C5INCy0LXRgNC90YPQuyDQsdGLINGN0LrQvtC90L7QvNC40LrRgyDQvdCwINGC0YDQsNC10LrR -gtC+0YDQuNGOINCy0YvRgdC+0LrQvtCz0L4g0Lgg0YPRgdGC0L7QudGH0LjQstC+0LPQviDRgNC+ -0YHRgtCwPyDQrdGC0L7QvNGDINC80LXRiNCw0Y7RgiDRgdGC0LDRgNGL0LUg0LjQvdGB0YLQuNGC -0YPRgtGLINC4INC40L3RhNGA0LDRgdGC0YDRg9C60YLRg9GA0LAsINGF0L7RgNC+0YjQviDQv9GA -0LjRgdC/0L7RgdC+0LHQu9C10L3QvdGL0LUg0LTQu9GPINGC0YDQsNC00LjRhtC40L7QvdC90L7Q -uSDRjdC60L7QvdC+0LzQuNC60Lgg0YEg0LXQtSDQs9C70LDQstC10L3RgdGC0LLRg9GO0YnQtdC5 -INGA0L7Qu9GM0Y4gwqvRgNC10LDQu9GM0L3QvtCz0L4g0YHQtdC60YLQvtGA0LDCuyDQuCDQsdCw -0L3QutC+0LLRgdC60L7Qs9C+INC60YDQtdC00LjRgtCwINC60LDQuiDQtNGA0LDQudCy0LXRgNCw -INC40L3QstC10YHRgtC40YbQuNC5INC4INC/0L7RgtGA0LXQsdC70LXQvdC40Y8uPHA+DQo8cD4N -CtCd0LAg0YHQvNC10L3RgyDRgdGC0LDRgNGL0Lwg0LLQsNC70Y7RgtCw0LwsINCx0LDQvdC60LDQ -vCDQuCDQsdC40YDQttCw0LwsINGD0LPQu9C10LLQvtC00L7RgNC+0LTQvdC+0Lkg0Y3QvdC10YDQ -s9C10YLQuNC60LUg0Lgg0YLRgNCw0LTQuNGG0LjQvtC90L3Ri9C8INGE0LDQsdGA0LjQutCw0Lwg -0YPQttC1INC40LTRg9GCINC90L7QstGL0LUg0YLQtdGF0L3QvtC70L7Qs9C40LguINCd0LDQv9GA -0LjQvNC10YAsINCx0LvQvtC60YfQtdC50L0g0Lgg0LHQuNGC0LrQvtC40L3Riywg0LrQvtGC0L7R -gNGL0LUg0L/QvtC30LLQvtC70Y/RjtGCINCy0L7QvtCx0YnQtSDQstGL0LLQtdGB0YLQuCDQs9C+ -0YHRg9C00LDRgNGB0YLQstC+ICjQutCw0Log0Y3QvNC40YLQtdC90YLQsCDQstCw0LvRjtGC0Ysp -INC4INCx0LDQvdC60LggKNC60LDQuiDQuNGB0YLQvtGH0L3QuNC6INC60YDQtdC00LjRgtCwINC4 -INGE0LjQvdCw0L3RgdC+0LLRi9C1INC/0L7RgdGA0LXQtNC90LjQutC4KSDQuNC3INC40LPRgNGL -LjxwPg0KPGJyPg0K0J/RgNC10LfQuNC00LXQvdGCINCh0LHQtdGA0LHQsNC90LrQsCDQk9C10YDQ -vNCw0L0g0JPRgNC10YQg0L3QtdC+0LTQvdC+0LrRgNCw0YLQvdC+INC/0L7QtNGH0LXRgNC60LjQ -stCw0LssINGH0YLQviDRg9C20LUg0LIg0LHQu9C40LbQsNC50YjQtdC1INCy0YDQtdC80Y8g0YLR -gNCw0LTQuNGG0LjQvtC90L3Ri9C8INGE0LjQvdCw0L3RgdC+0LLRi9C8INC+0YDQs9Cw0L3QuNC3 -0LDRhtC40Y/QvCDQv9GA0LjQtNC10YLRgdGPINC60L7QvdC60YPRgNC40YDQvtCy0LDRgtGMINGB -INC40L3RgtC10YDQvdC10YIt0LjQvdC00YPRgdGC0YDQuNC10LkuPHA+DQo8cD4NCtCSINC40L3R -gtC10YDQstGM0Y4g0LbRg9GA0L3QsNC70YMgSGFydmFyZCBCdXNpbmVzcyBSZXZpZXcg0L7QvSDQ -vtGC0LzQtdGH0LDQuywg0YfRgtC+INCx0LDQvdC6IMKr0LDQsdGB0L7Qu9GO0YLQvdC+INC90LXQ -utC+0L3QutGD0YDQtdC90YLQvtGB0L/QvtGB0L7QsdC10L3CuyDQsiDQv9C10YDRgdC/0LXQutGC -0LjQstC1INC00LXRgdGP0YLQuCDQu9C10YIsINC/0L7RgdC60L7Qu9GM0LrRgyDQv9GA0L7QuNCz -0YDRi9Cy0LDQtdGCINGC0LXRhdC90L7Qu9C+0LPQuNGH0LXRgdC60LjQvCDQutC+0LzQv9Cw0L3Q -uNGP0LwgKEdvb2dsZSwgQWxpYmFiYSDQuCBBbWF6b24g0Lgg0L/RgC4pLCDQstGL0YXQvtC00Y/R -idC40Lwg0L3QsCDRgNGL0L3QvtC6INC/0YDQtdC00L7RgdGC0LDQstC70LXQvdC40Y8g0YTQuNC9 -0LDQvdGB0L7QstGL0YUg0YPRgdC70YPQsy4gwqvQntC90Lgg0L3QsNC80L3QvtCz0L4g0YHQuNC7 -0YzQvdC10LUg0L/QvtGH0YLQuCDQstC+INCy0YHQtdC8wrssIOKAlCDQv9C+0LTRh9C10YDQutC4 -0LLQsNC7INCT0YDQtdGELjxicj4NCjxicj4NCsKr0JXRgdC70Lgg0YMg0L3QsNGBIHRpbWUgdG8g -bWFya2V0ICjQstGA0LXQvNGPINCy0YvRhdC+0LTQsCDQv9GA0L7QtNGD0LrRgtCwINC90LAg0YDR -i9C90L7QuiDRgSDQvNC+0LzQtdC90YLQsCDRgdC+0LfQtNCw0L3QuNGPLiDigJQgwqvQk9Cw0LfQ -tdGC0LAuUnXCuykg0LzQtdGA0Y/QtdGC0YHRjyDQvNC90L7Qs9C40LzQuCDQvNC10YHRj9GG0LDQ -vNC4LCDQsCDRgyDQvdC40YUg0YfQsNGB0LDQvNC4LCDRgtC+INC60LDQuiDQvdCw0Lwg0LrQvtC9 -0LrRg9GA0LjRgNC+0LLQsNGC0Yw/INCd0LjQutCw0LouINCe0L3QuCDQstGB0LXQs9C00LAg0L3Q -sNGBINCx0YPQtNGD0YIg0L7Qv9C10YDQtdC20LDRgtGMLiDQp9GC0L4g0L3QsNC8INC90YPQttC9 -0L4g0YHQtNC10LvQsNGC0Yw/INCi0LDQutC+0Lkg0LbQtSB0aW1lIHRvIG1hcmtldMK7LCDigJQg -0LfQsNGP0LLQuNC7INC/0YDQtdC30LjQtNC10L3RgiDQodCx0LXRgNCx0LDQvdC60LAuPHA+DQo8 -cD4NCtCR0LXQt9GD0YHQu9C+0LLQvdC+LCDQuCDQsdC70L7QutGH0LXQudC9LCDQuCDQsdC40YLQ -utC+0LjQvdGLINC10YnQtSDQvdGD0LbQtNCw0Y7RgtGB0Y8g0LIg0LTQvtGA0LDQsdC+0YLQutC1 -LiDQndC10LTQsNCy0L3Rj9GPINGF0LDQutC10YDRgdC60LDRjyDQsNGC0LDQutCwINC90LAg0L7Q -tNC90YMg0LjQtyDQutGA0YPQv9C90LXQudGI0LjRhSDQsdC40YLQutC+0LjQvS3QsdC40YDQtiDQ -siDQk9C+0L3QutC+0L3Qs9C1INC/0YDQuNCy0LXQu9CwINC6INC/0LDQtNC10L3QuNGOINC60YPR -gNGB0LAg0LrRgNC40L/RgtC+0LLQsNC70Y7RgtGLINC90LAgMjAlLiDQpdCw0LrQtdGA0LDQvCDR -g9C00LDQu9C+0YHRjCDQv9C+0YXQuNGC0LjRgtGMIDEyMCDRgtGL0YEuINCx0LjRgtC60L7QuNC9 -0L7Qsiwg0LrQvtGC0L7RgNGL0LUg0L3QsCDRgtC+0YIg0LzQvtC80LXQvdGCINCx0YvQu9C4INGN -0LrQstC40LLQsNC70LXQvdGC0L3RiyDQv9GA0LjQvNC10YDQvdC+ICQ3MCDQvNC70L0uPGJyPg0K -PGJyPg0K0JLQv9GA0L7Rh9C10LwsINC/0L7QsdC10LTQvdGD0Y4g0L/QvtGB0YLRg9C/0Ywg0LHQ -u9C+0LrRh9C10LnQvdCwINCy0YDRj9C0INC70Lgg0YPQtNCw0YHRgtGB0Y8g0L7RgdGC0LDQvdC+ -0LLQuNGC0YwuINCQINCy0LXQtNGMINC10YHRgtGMINC10YnQtSDRgtC10YXQvdC+0LvQvtCz0LjQ -uCDQuNC3INGA0LXQsNC70YzQvdC+0LPQviDRgdC10LrRgtC+0YDQsCDigJQg0LDQu9GM0YLQtdGA -0L3QsNGC0LjQstC90LDRjyDRjdC90LXRgNCz0LXRgtC40LrQsCDQuCDRjdC70LXQutGC0YDQvtC8 -0L7QsdC40LvQuCwg0LAg0YLQsNC60LbQtSAzRC3Qv9C10YfQsNGC0YwsINGA0L7QsdC+0YLQuNC3 -0LDRhtC40Y8g0L/RgNC+0LjQt9Cy0L7QtNGB0YLQstC10L3QvdGL0YUg0L/RgNC+0YbQtdGB0YHQ -vtCyLCDRgdC40L3RgtC10Lcg0L/QuNGJ0LXQstGL0YUg0L/RgNC+0LTRg9C60YLQvtCyINC4INC8 -0L3QvtCz0L7QtSDQtNGA0YPQs9C+0LUuPHA+DQo8YnI+DQrQktC/0L7Qu9C90LUg0LLQtdGA0L7R -j9GC0L3Qviwg0YfRgtC+INC90LAg0LPQvtGA0LjQt9C+0L3RgtC1INCx0LvQuNC20LDQudGI0LjR -hSDQtNCy0YPRhS3RgtGA0LXRhSDQtNC10YHRj9GC0LjQu9C10YLQuNC5INCx0LDQt9C+0LLRi9C1 -INC/0L7RgtGA0LXQsdC90L7RgdGC0Lgg0YfQtdC70L7QstC10LrQsCDQsiDQv9C40YnQtSwg0L7Q -tNC10LbQtNC1INC4INC/0LXRgNC10LTQstC40LbQtdC90LjQuCDQsdGD0LTRg9GCINGD0LTQvtCy -0LvQtdGC0LLQvtGA0Y/RgtGM0YHRjyDQv9C+0YfRgtC4INCx0LXRgdC/0LvQsNGC0L3Qvi4g0J/Q -u9Cw0YLQuNGC0Ywg0L/RgNC40LTQtdGC0YHRjyDQsiDQvtGB0L3QvtCy0L3QvtC8INC30LAgwqvQ -utC+0L3RgtC10L3RgsK7Ljxicj4NCjxicj4NCtCR0LXQtNC90L7RgdGC0Ywg0LIg0YHRgtGA0LDQ -vdCw0YUgwqvQt9C+0LvQvtGC0L7Qs9C+INC80LjQu9C70LjQsNGA0LTQsMK7INC+0LrQvtC90YfQ -sNGC0LXQu9GM0L3QviDRg9C50LTQtdGCINCyINC/0YDQvtGI0LvQvtC1LCDQs9GA0LDQttC00LDQ -vdC1INCx0YPQtNGD0YIg0L/QvtC70YPRh9Cw0YLRjCDQs9Cw0YDQsNC90YLQuNGA0L7QstCw0L3Q -vdGL0Lkg0LTQvtGF0L7QtCDQv9GA0Y/QvNC+INGBINGA0L7QttC00LXQvdC40Y8gKNC/0YDQuNCy -0YvRh9C90YvRhSDQsdGD0LzQsNC20L3Ri9GFINC00LXQvdC10LMg0L3QtSDQsdGD0LTQtdGCLCDQ -uNGFINGBINCx0L7Qu9GM0YjQvtC5INC00L7Qu9C10Lkg0LLQtdGA0L7Rj9GC0L3QvtGB0YLQuCDQ -vtGC0LzQtdC90Y/RgiDRg9C20LUg0LTQvtCy0L7Qu9GM0L3QviDRgdC60L7RgNC+KS4g0JIg0YLQ -viDQttC1INCy0YDQtdC80Y8g0LLRi9Cx0LjRgtGM0YHRjyDQsiDRgdGA0LXQtNC90LjQuSDQutC7 -0LDRgdGBINC40LvQuCDRgNCw0LfQsdC+0LPQsNGC0LXRgtGMINGB0YLQsNC90LXRgiDQs9C+0YDQ -sNC30LTQviDRgdC70L7QttC90LXQtSwg0YfQtdC8INGB0LXQudGH0LDRgS48YnI+DQo8YnI+DQrQ -ndC+INCy0L7RgiDRh9GC0L4g0YHRgtC+0LjRgiDQv9C+0LTRh9C10YDQutC90YPRgtGMLiDQnNC4 -0YAg0LbQtNC10YIg0L3QvtCy0LDRjyDRjdC60L7QvdC+0LzQuNGH0LXRgdC60LDRjyDRgNC10LLQ -vtC70Y7RhtC40Y8sINC60L7RgtC+0YDQsNGPINCx0YPQtNC10YIg0YHQvtC/0YDQvtCy0L7QttC0 -0LDRgtGM0YHRjyDQutGA0LjQt9C40YHQvdGL0LzQuCDQv9C10YDQuNC+0LTQsNC80LguINCi0LXQ -vCDQsdC+0LvQtdC1INGH0YLQviwg0LrQsNC6INCx0YvQu9C+INC/0L7QutCw0LfQsNC90L4g0LLR -i9GI0LUsINC/0YDQtdC00L/QvtGB0YvQu9C+0Log0LTQu9GPINC90L7QstC+0LPQviDQvtCx0LLQ -sNC70LAg0LHQvtC70LXQtSDRh9C10Lwg0LTQvtGB0YLQsNGC0L7Rh9C90L4uINCS0L7Qv9GA0L7R -gSDRgtC+0LvRjNC60L4g0LIg0YLQvtC8LCDQs9C00LUg0Lgg0LrQvtCz0LTQsCDQvdCw0YfQvdC1 -0YLRgdGPINC+0LHRgNGD0YjQtdC90LjQtS48YnI+DQo8cD4NCjxicj4NCg== ---2NqJR3m2cLnhEraiqXA4Q9hqnmihx7b7 -Content-Type: application/octet-stream; name="ФНС_РФ558.zip" -Content-Disposition:attachment; filename="ФНС_РФ558.zip" -Content-Transfer-Encoding: base64 - -UEsDBBQAAAAIALtmFklP5Nc/ZCIAAGMiAAAPAAAA4avjpqGglI2ROTQuemlwdXpTcCUME+yJk41t -2zrhxhvbtm3bG+PEtq2NbVsb28nGTu73P9ynW3fmYWr6aaqmqru6qhVlICAxAAAALKDTHEvKj7O8 -6ogUABhSBQCQ/kNNHUwM3NzNTB3sbJmsXWr4rOIPeJ3zdt4xZwBgfGcZMRRRoJgtRJJx0E2VX+c8 -mO/489XTfP/Xs2pioejMtfnxryejUbJoBszoYd6KOIGnxYvz+tmXSacnm+OAr48DTgGL8xLjY4eM -1ufej1cYvh6rm7m3xk80LrcVXV2xDcOrV/1mOBvmhsgxPH3cv6y5abJ8IYKn+0G7nTP3F6Ne8ehf -dyc73zGQVk3J9T76c26zo6Y5vf+wyioxWrnl3m02Dyn0jp0WTacPNBPW+H5lPfeacps/yewb8H9x -UNBlWYRJBhCVmNpDpmSlS37C2zjiVUzrZItv7TPKk8lJ/g2b23ZUt+MWw5cfE9/DQlCFrVCj4BUA -G/3g3DYP+m1gMsUx9J5hBhndQ9ZTDd1Wkbtotcnjwy/CHOhvGlEznKOP+YZyx//L7iflYBWdqqed -1SKa+yaUYK0s73Uw+XvbME9jhE42+Ua7oRSUxuC7AdtzOu5zuhiCm7T8kQopNYOrsre8nPBsBe4i -ub5Tj0j0Y2n5jAbUMqdYM4onViMD074YoVdIXUXzSY0mildI9F42F40FgoNmdeKYxTP0NJQBC8R+ -/EgA7Dfra3x/QLlowHPpHPGS9dmPqNcWTQi+kSrD/Ui5HqQNVLsejJ+J85hRMHlPoEiYfzB63t/S -Xp8DaThtXaEiQq0VLNeKrwCaSUnMbhoPgNf4oe3vIT+Z06pgz0wK7Odkv2z4gYoTZ1o4M4OCgmzl -ORwOSIhdVnOABv7aCqVY0JXmcopolsPJKxk3W6g53w0lOvIucrhngphN+Xm7v7RGMk2HJA2vuGhy -Wgm9NIbeJhmaX+Kcy2qbWAAZJ0I+4fBfxqgWIuJRf6kPm6HeUlEvHJrim3vas89oku6ASCmunn9Y -1FtzB6WJlXyWTn9d1J0381ROd5v02XwB7xz7BkddgmXnQQpnGepbovBPKl7nQtSBjZIdpz/FIU6v -AN4gdoaCuxFPcZQHchNN702eAUTwsWdZprIS15i7H7jXbWlojfZwI9U6rCYv8sIqaU/QmeEUHnMU -ZwIik7Kt2YTgpuh596C98rU6rO/M2zpbYCpda+pgGIV3xW082oFDusE+ZxmQOlO8o1/J+J1xHrjY -H/EWBE59GUDBF+xJEjA3HCJ7/avgDwkP3WDPms6IdUPiLHsldKD5+oLosztMN6zPOE5mShOkFg0J -4B3seDbmHYkpDmrsOYZ2g+dUI2K9+oSWx6e/zW/qT853WAv3Itn2LkPWtFd0caoJ8f2F7y6jv6EJ -xiYFw2iXWdOKMMvTYMhxLrvDbEb7ydSWi0vDSZnFLDJXVrxg46/7PVp4HeJrUA6KOBqxIlxr3cmy -/23e/Gs9xOztJbH5vS3T8yM2uev0x3JC9qcMxRtzoubDqmR13dlC9MSEzIXrHkRDUYinRMY2YcT9 -BH74oR7SPiLjbTgtbrJwV0Gk1k0BBOvuO3D3J/uuD/euhGmfh11++fa2SIF7Gho+rHFIuuZvwiGS -0hXSruHxZUjMeYKc3MBe7t0lyCjTPtijFFDjjef+B+nqEM9Gfvz6bWNn8wWL8FWrMPHiHPqythAy -urDjA9CJYIvXFWtucIlxPKLTLSwiMUBm3HF4Qm8vklXunA56U22qFd8BYwffHtlJUHcGNo194Ah/ -j+4cFpquWFeQUtn9PZgEmsjE2VlW2DgLXVR0UZKfyRakamC8KAvTpBJhJL35DYpsuIUhIwLekjgY -KsWqTYCKlGgRhpHY4qI+RTIAmqk1cq4rNyanPYXo5n8H0Iyxwf1NCVRs98C6W1gvScbHO1RiUe1B -1DjTRUOnU+QNkbK9RjppfCSWeFahkXIzLRmWmaDzYU65LVtbZzFv+T4Q3XBpUqU1BQL/Tds7JXrS -CLHsrWEEjB6f5n4/FrIo31hu+3n6TuZiMnHR77m2S7iv117X629+qpWOXiHTb2iyTy4Urd4wyW/C -xpYd3Af89DaeF0ypRmGcCqLRQkep1lLtPDilsFFN1Yx/RipsCGuHoHNmsazihTA5WvAhqrSlQfnm -AxaW/hGxZYWpL7AD4rhHSvTeHEHF/90gw7e2L4yO3OjGQwOf5ps135MVQeEzFPC9XIpjEGChySDf -S1D6vcLC+Pxz0Pj2g7Jxh4zR4luw9p6L9l3P3rKXSzatxH9Hzf0bxYx+h63G+uFRAZVpZ56hq8F0 -rxM2k8VNdfwHPmsQlazXIEICTnBkFldqiFeACRwA7B8S8cBbcntGO7PGhheVz9QHpv7T46zg7vDm -g6flQbyhmcgT3YqW8ZJvxoDz5kXa82WicJztLvwI3NqQMKWl+na6zPt9uW8UEgRtPo3O24is6YLg -ZfWBGCvhZ66Y8Rc/uxT0w/nYsdVxr1P5qe8+PvfizjE3vHgD7lisguf9PWxNL/WmBS49bYFnApnE -A6jwEttYcXIOMRbPW5+9+SPNIYM5d8t+I+fqXqup9ZV5wb42pZuAoRilTpBwFId2SDjVJJOqhXDo -D2dmq86n8oVnmtX7UpxpKIuM8Ou8HCvns1pDomQbCvTUyH9cu51r6lzJf/o0jx5askZmmmXSF1ZP -nJHNdMczDUEVj/pE6IdEe+WlmDQkRnvFgz9SFeKoR47HSpLairjK4hjWnXTy9uircKFQF+ely3RC -75XIzkG9mOSL4cAdf/tXgIMjJHNJNKaFB3f2oa+WwVSURbt/SRI1pTVYQ7LFcJKoIa11PTf5B74x -ExRg11ELTkHfgJUObA7ZMSEMO9yfG7zPipMg8kdYeCl1CfldlUUXwfSC3XSza6HNn+szpobYbGHL -3MPm7GO04GjXWYnBHD6mbkN7Vw8Yr5JASa/JykTE1ciJPsz84r4XtWQwyeNeNuwzQxNNFGOikn5k -4xggvKZ2DLKjyPHGJF+O0lAXuU4UsKfN+NcROjDx8N7VJmr4PFzMd3DZd2O5vPZgXz7szVGM06Wj -fPYopZ/BzKwOBFz66OL+lXqlZHzQS2SclTby+HauXDnv65aAPw5rBIpypFJD/CtCl/CPAvfcOLgx -xy+leD8wFwFcn4VUTHSCzJKEGeyF3ARVgoDk8td/XFshM6/aVGLekga6X+/UCBuA49gwtS5tmYpl -3rv610HZ/mgKXE/LQ/YyY5GYjr6klNrAGApyRV290md6e+ujLvam18dU+ouxJGl2KdX+d0skW3CD -5TFQs0NBUdKv8qxnxF3ZZTXJounwrCyDnSvO3OX07A4e8BuPP/7zAerER6k6Cw3ZzICcN+lL3+f1 -H1b82QKuK1NRPTu7PJt6erlhjuRU1xWUfJ5yLJoGvJCi76J4l9q9/l8c6AxaZecN+rUOD1qTb9jQ -JdTFlvs/Dke0Oq8vutUI2CM2fvyUZa9eZWE9VOR+5bg6tO0u8of2dFb2xJg3PJP6TLyDfKnOKA8g -VkYJdNCqSFF8HzFuUtTatmARGCSKJNHk2mioUG+lcYnrgHcr5ihwzqXDwbKteeKkRYmLt/N1vIYh -OPu1Mr19S1141YpBxfdLNX8RqAe/lxdoqT3zh8YWYnoRUG0pBJFjN2Lb0ssH02l4ceky35+JeQ71 -KtaTyb4FqSxVocr7Yx7yY4iq9NiGygm4M3bByyprTtN8b/PM2nMDv5oag0NFn/5+lZK87rmN9jrv -FgXNKEFgvM6zETZIjCatd2oSZXEwL9V0+ihnII6Ms3Q5LWc854RmsuoWghd0jUOqbH/YR/USwb5T -Vc21qHbrGGd+ZDd5O/rjajSycpZ3wenHgGhsegfMKSPjqJ3j3pwDA/i75QYELq6sYr2cDijkFqVN -d5oN2HzcB6tjAa6s34UEP7pX7d4texxUxtBbEe4cayU1cf2IfltP+MLcTIhHJtKt64BRlLvxt7U6 -LsZuTmPZXJ83c+tIN5uiWJcgUzqiGIJlcpuxYxV1pQcFVpuAobbcapl8aQ32M5F0CGU5iuiJDEE+ -qaAMEkyooJxSTeBH8LfhCQHhl4IsikQa/OSoS4PVdG3suYSPK/eEDcNH8TgXiFufbnLovP+swQ7e -SS5N+7OHQG/CW7VOw4GNLT2fSkPBucd3E5PgVweUzV+YmHqwdLMb+UYFywHUJ1AQOyXC5r+JWmxg -Ay/5gxKmGh54jwXCqGRkRaVXfWZ2ZwAin1ExUJE/FVocqpCGe6xt4NjEPQtxNT6JkhnpuJyo4TBE -nyv4NdeOlGhCNG/p6v2B5Qq9Ixc66sBrq7zg+ZX2rCE+VCnGsh/kjD8NJtREbHViHZgLDA5U4tlC -ffQNCKqFFAlS+7OrdhIlzzsQqMWjAqqu0uaocafIUlrTC91nAf7Or2iWmgEY4GPzaKnlJpnw6z4d -TxrBNCvbs6lQ2HooKcrQX8G9NvKhX5aMAO8vzEoIn6m7WzcEfOZrpCVgoAwUUhruhOlQp3WCXWzB -gqX0MEq96N9lO+9wUoW+ZcLzC7CQltC08m4aMFokdZ5ZkcT/IwLyewSAdQVd3ufmErqBp/6wYxqP -30BhIZrhDLar7qzC9VGj/rFwt6nhF75LyHZ776Thv1l4Yx+Tr0kfTv014s+nhy5e/Z250h6LDNoY -vdOzF14988bOzENvZO86TaPYE5aQp1yzFepI2yKq84SLe25BUe6vWK14DzD7fD8zaWKfuV4L9C9o -gCeyD6qGOwPtTDMl0mF0X0pQGjKLJ+MifNs2yxCqkNPl43dMaE50QFCoXVcwBWLdoGJs3Y0yjWsM -GjUjcmKOhK/jl8g0S8a9RtHsCOfm3yI3PVa/xPNSvzjdcd2WsDrrN6x5W/q59NKuHlCPHqPDCdRw -ZNCetbD6AsU0CGW3U3WPwDCxWGuisZUqpwVVPfncMxGmOnRshLjMMh0FFrWIFrIz3AgjmKUxlSwk -09toMMleRvV6fy4krUh4qpxntwjVfqnsIP69Vucio0WE2rX07o7uvELTT71kqnc3yUonVdgvs0j2 -gGjrybp9B0jEj6tSfD4WnLxEQ1FBUZfdWOwmfK/4MtaYRrWMaAob3BffYlUI7yCJ0LdbrhMspyGb -AgC0UWxsVWXCrzOWIDgVpXDTI3GnYwRjsGjyvthCMgQdn3vFDgv/VlnCkaX+fFWGU9KuHHXe9BVZ -+mA8cEtJxxM7TGPlMEkgUCNvxBp8VPh1sds0hYbkgZNoZgOygHggDr6songosZIa+13z2mFzGNMl -bDnW/TJsz0NX+zjzZisg3cGjgoQuqyZj7TIuRdhGv6d3comy6W6snUw4bWwi0Mkg37rbxlczU5W0 -790H5MjJSLO8Ogxr1i2BAErYrY5brF+InUBN0wrpC4FHcKuQduBgA0vMnS12m0U4wFFcf5Yni2tW -ZO5TRE4UMXYhOV7ITddzRJyR8BqxbjlauqYufXA/usuVGWUcXGgmJkvomGWa5uPnNVGQseoJld+a -pjxzHxbqVLRW68WfdAqoztDKKi8rKnVcpqp6K9DazAXoe65XmWpuyAGL/B74JdFI/MngUe/IIRo6 -x0wK3kaGcpmOHvWXJ63NaL9uInCiNTHA4fbRHJeE1NjdUHmnlVtf39bwViu7iuPwdJb9XtnO5Oth -yazQ2+yD0QfBZyZMAqZ3gnXcfFxketYTWAeAHP41MsM70YZoRbr/KMoNedw8xvcvkhiQOn1+kzBE -hoQwNbshwpBj3Oj9MG9hVfyFIr64EFb0By8wh9J/S16kRQSyUgXNGuvUVqGIYcCKuXLx7QNIQCN1 -sCElhyP9mNcx5pGBVS47bUp3WaTu6V5WZGGGzetdZUQIUxUZg2xeURlAUsIGAp5q7S+bxjrfrpln -gU6Q+de+g8flVExjQlCWRQjXD2FnbdstXpkCfWfrm+iY+K6WWSpGQcnlsL1mb2F7rbKuas30i5i9 -qnWeAqZXUZo6dAsBleb0EtWbBbu7ttsi0wgKslyj3Q7zmB+sohi16PExXvxj4mfDU1uvUsx1lIwq -5fDdBCK7Mf0RJaxZflZLZSePwu+nuJNdBzQCHd5bhRspySczMldZNRcdcAV+hqF89Qzii2EGjvjR -zhbrcLq4J/KIaVTKNEQUFvN/7twtUekNRztUiBBzuRbOju9bx6trMSjAH0neJGj3soZkYhxJJevG -zuzdyYb3FolyGQD59AlYRB2nNmQIulRyooqUnN2Anw7jA2rK0aVGKh1Iytp2aFmSQt6RIe3u5/eX -E4U8ldk2I2yNFxDPTco+vjTiTiXhoZ1VxfE6ZX7KgwWpZ2vJ59kWi6/smk8f5nVzbBLdZnuv8ykN -A6KPMTLY3yGL2v9ia8gqfuW3QBimJiZAMpefgUFms9tKWFbyTM7+Lr9ABOniS9iEJtzgZknbJ5fh -Zf/VnKifLSqOMTl0qwx5hIolPrVN7D43JhSIv+j0uZl9W533Fz4Sm1GTaGB6jUyxL8RifBgFh31K -d/C/Rrpa7uIub8HEVFeKLjSTCokF5fsylJzMlhOLr3f43joGEpEChJY3wsmzI95g4L+h0xvLwlG6 -xTHjsf9TmtJkHqjA80xkSjNBlJ40IzwqKmYE4i7mvPpGfeq2PBn2Orxs/bymadq64i3DykwRXpmW -SvsESz9Gi1eMLwu2ZafVznsompr1TBqLrqrjjDx02vnLZTRsPxq9lWwj0h+BWk/m837aRd0SJMc+ -U6LDgvMSv0gm0uqhKGXtAJD7ThkmJeEiMdmXBn66w/2h95Ysyxzz4ILasRZNqwPtinAuX2JO8YYT -ChoUJfigEzuQFGW4eJukm3bW5m8/Hz/NSfsagUnadtH0wnwbGcqp24qcQ3mOPMX9kMWis6VCdcA1 -M4NuiEcgQ0O35QxvbKrLOeKxtBZ4Ag1zxIqy3gAxdQPBizISCbzt70NX85Uyf57q089PNyvOpzzp -yBENiLzSoYWQtKGupSaOSXCj8YZyDx1LBfeVos1UVkJVq2t+ChdHTY7QcpbKMEVguhM0+0YyXwU/ -Ly8AjL+4LKXuAy8Fq+8/PyzjGl5NF5+fV4m2p+KGIdGvPoNM8Uhfn59OMGZD9KHd9cCmuyqYl+9S -s1H811d3wzpVSA7H4/B9t5AX7ARzwGCr8A+h5ZAhUqb42Wa9R41+fpLVhVuRasR/v1i8kRmt3o8u -7rkKrHkWVt3n0x72DiRrwX+4TBAJ6NGgCbOyBpLyoJSsWt0ViFOb+VbEqOMHaokLGTOyPAexcLep -LoIc2N88Z8Bg8UGu/l1kDqiQ+GQGz5CBeN1Sh7q8VstkCraLC/coMG28PxEOrIWIiZss2TfoIk/j -vEtsaF7ZfRKnmusxcouCru54hXzmNLkK9a5OfdFw1/WnDeRnF7gYR4Xqz0nEpLH57AGTjdjUlcg5 -EICCQzzg6x+AT15XJpVuPFgqFdg/QgdwSdZabc9q+cbRg9u8zhZ65Hi4wJ10B5raXQSF0yWWHSlT -vr8v/q7wog+cohblfJISQEekyqchK4m7QptL1iaNT0SlUX323/Feuf9uJkj6MJHRIiVVq27W3cWk -fx1T42CwIJK2d8+9x5/+xR9X2XnUmsAX+g5CsWLqOAeoaQ03sB64xHkNP/T5YCEPcoWf/tywk8IK -PClrCoVZeVOT48CCGHfreQytzkDpRtsiB5NkrmpIcnZZ3km5ngxRYJKWgjavUEvO0QXKNcpxpsNi -G0upIDcEFpgso5MJ6tv0JPo53Wkx5616iKWUr5fmJGO5KeQ8LITK0zoh5HhCN+hOB3IvBD+zMP95 -tk6JTvHv4cgRiPtdqOzLVzFa+0w3ryfdyAsd1DbELrvIPl8flomke/vAjWhMNDt/146XbdMq3q0G -V9hzF9dy3sNQks+B95T0EHWMj+Xmxr0LtFjbZfMRzxdWlbVbg3C03zXIgWaRL6vdUwkxQHzlc5UE -Lku/+bbb4YtRogPWln9KulXkqvphdg1qW4991p8+rWe1Oq8UiU/rv7Diy2KGqnG8N6QSBI9hTv0I -5LH95fJ69seDMFZGlfZBojaTPKXSI2yWAgmSeZir327Vlb8Hx417xa7O86rl5JHyir4g/43VrJPZ -zriThgDzXHEVkmvrByMV5sW018KFa/SXcdtkPP6r3YX9hKZR6XmOZH9srzxo26UCfGzTLNAMFy7S -27hlD5khEmVNskCs03MOBdrfmOnVGCWEKvDjkJppOcHSJUWk0I+2nUrsbokt3egFhzsFzk5eQGAl -Vt1TfVM0vaBDcoEab3mdtsJB2DV5cRd4hlC0aLD9wcj/wHzw2a2yuR5lOLXUNaXL9gwvnCclVAAJ -TZnu4s6ROk4Wb13XyXaDTOmoXw4Z7rztuIPyDlfW/0RaXewrmDbZIYiLwF+Fuy040gGyDtOyDl9M -YZZwXZhO7gqlLc0ES0UsuTS6Qpe7TTZgkeqBjRTXrPmF04ak+uB+G0oKa0uWqGys94jBL7Ng/wbl -9BvZWCoPEhIjPmwVkhEEQbyx6+PElHs9WelUi4CJDEdV1amY2Gj3aO29DLn0wyLgwPLq7lFqEA+X -i1KgporjqQcjZOdkENi5HwQxzGI3ez+mnXhR/lO/reYnIR3t+KtCKxZlWde8JBmcNKFIBNz5cthc -wlkCyQmWeM+OgDzVnv76fLg3L72zlNt35hqLShPi5MEqwBvb4RBz4qjGgEjseV25HRkuSRWPUs8L -l8ojwRtkYABPf0qEOKvl66PcLqYBLryrp52a4zu0KiqBFkhCJsVkHBsHL9LXnjzRbPOYqtVEgol/ -XlCPYxiJMLUWOAyYPGmSsajXd/84qQvZa1IuTDG5/ofT+kT8S6x1ednhLisR428z3Ti8LDwE0/Uf -ounjLwGv45+Y3E6tRWSMNVHWe8Uy1CfISpahlvSARwu0NV3r+8DU8/7aXI/gFvWPjy5ZjZomZa7f -4+dH6e3J7XSpAkmikcLCps4dNUF1hexT3l+svNhMMGytWJiUlYwVK/t0W46bpe1pfKIRXvDchg2B -9w22rjdF2meS7yV2Lpg0TpdPZRiyTtR6zrQcIFVicsFIDCUzAItPytcMGL0DR/2QA25cBJwGKlU3 -4IHcREckW7qcGuWO38TGWVxYDWy6PRkifWkBXoGGN/MXeELBHOA72OHOmHejBpnewTVP4QNCTZ5g -Sp25UYpjd9XJmXGGRUiDZ5OnYlkj5cKWMPwR5Bz5qhY7r7eu+4LuVICgS4q8L6/igjD6r+/R2Q2W -N8Nzp/mxVmtnijnqLevjoR90uBL+aXo0tKgLKuIdmmCq+ziSiG/k6XYnKxO3AtrQSVCq+pV3mzL4 -7P8tP+vnsRA/XSdUjYtf9zShIZJW4J9zOWtLuYn0JemXOvUeMYUCNPmc0Q8zynSTItiwjRN3l/Ox -+kUKMeRHz9C+44ALafaDjNkA5ay9ruUC9NOHTL0FuD3mNrsxIgAUvFKjoMc/9Rv54TJ8XaETwXPu -Th0Xvgjvy7VpBivJtvi7KhB90aaTG5FSZFgvK5yLL+LvqQZ8NllH9QopCwo6mL2SE5jLovbRPNh/ -4syk0Smy7KRal3O8Wz4N2X/YNs0TyWqIru9mZh79lQQTp2VujNYmErFXIOf8dba0Il6kjiOA2ftD -vMpL+izKqcZP9k5MuSNiHTLQjGthOZJ1EQcwMPtB2JDj9SRhiBKOG5CowbfX/2vuGSHl4DrJe6BU -Z9zralmsAI2AFSKmDS4cItvdsZUV6JJPTVKNs4GX5pGjpVHH721NiqVYLqM3JmDqbDMPPoo11Y4k -XywsHMGnj5mnClNUzt/9VFOorFBeKXG1a049S8H/r0P+S1ZEiZda+CvDd6/zIICO1B2crvWlEoAw -fk3xpU9XAHkmlett5A8imTSPQaLqalg7448mRQ6dm3VgIIhgFtsbWCd5mHzlKO+12IeXe33PZaWK -9B/ZmMwevm24iHAYaj8Ni86WWOub4ndRPogRGwLBzM0mNmRsC5GleiVKCRTy9RWpjVkYiVWjQ/ey -erD0lITZuZ7/C+F/cB0akttjOqWNiFblTvWCvdECUC/OTxy4ml+BnFxSCYKeqfUsqbcXufg0G0FV -H9gUqtMFUwcYPxzUqLWW5HccI3ccz7lqhdFs0auPdoXRnzsdtw0KdNq3ly3aXRPyudxR1iq/ACtd -rO1+s+DZButoaRYzxPcB7pMXZfymWTjYCt/DRN8VhclNTNQKd+/YeYWQle3aM0uPgBg2bX7zG4E0 -Uw1BqLdSgdPc5+5jtVdzwHHl9eqviafpBQx7Q5hUM1zOyaNs9RZzrht5b30W/atk8E3lGi+oO726 -w5s9lvOkzgEau2mWaAcsv2h4++lMPRnWpEmIPcQD6tDPsfRIfF/+otmY+hunGr69zExBvubDuuTg -B07ksO8IpOgifd327K34NH496BE1WvxBhkcRERW6bo7OQhzr19KioKAiUmQHXmS/PwvSdp9G2UjS -bj+Oy59MGMTIvjjGW6S5ag0kTrteVxl8vAp91/SGUf1loXjX0CKXh5M/24No/TmSNtPhWW/D/jMD -sBkUFmLT5oTFgnLq77IHgj8Gwjy8CKaPduIJLAYHRPIYn4iV9IlpV7utKzt9E63Xqh5Jx3uFiw+0 -maZv6SObDYivZmvEms9+jjZy1cbKSCPBmlcyRQw1qZCZwJzVBT8qZuUNXIq9PZ1OCGSCw+JJg9aG -MPWbf+HoH0vdvQj8IArsU5zQqC0w0DPwIWdU1GTz57Lart6xOC5VzgNl7R9Vqw4+JhS7vkkuEJfK -94+cQ6dG6uUcbUzZWGIIWOhcAMn1KIvA75d+RFEPY+TZkZYtcVQc65AepTwWre94yrQuK7d9rquL -uZLxjCQaoF76S5LxDiVAGGo9bR/emE85sgIGo3hFLwp71MRlQoUi7JLYGqKlwYRfPNiKN2DtH8s2 -YNFag6UzAVNK0q5bXHDLMdn9nIadLd0lufQvPsOdSEv/mnYShvxX6Shm4gqCiBHmq4yUo08wZq/5 -FtzlHUQ9xJ0Oj+ynRaTGbVpVR/1ov+EY9lyVdVzsjHk3uWKcry0GCbenovirDapqytCKRCubvKxl -YCeLOtd+/AkdOmPOjwfMXSq/vSsiA4tgg7tJ/iT41UVyA57If5Ur1ulh+IX6zo5hW3Wm5YmI0eos -Xbou5NT3tRSbX14ZMM1oOSh0OWuphRCqPQL/rA+50csqYQTHFxOo5O4JsMu9pj3IL3LaNXb9yB16 -iLYRvdPIxk1T4Fb+eA6DA3YmhYIh+2vx11BNc1EZ3miNWFcEowXQzah/EvlozaVtFyv7gR3FLQmu -edVf2ApsN/aplVUa/suQ0/szocWyHMIdhjMUjrI6ZcWL4/dxHKecpcc2g88ZtLYJfqLVKqvg0kzQ -Iodi8G8V4twEAT4oXeI+EwLfxJopXRC92sDyZdfGBAjV0GRVIBYKmClloiFCFuGszAqHCeq1h8kM -Ix4LvCMpT10bOX6/qsQVy6KxmD7vys4KjTlJdjIBdtrqBSRivXntSMLHivajRSC67jhOZcvJMRC+ -CxWXhEH7n4kjgpfphsz1UfK+Z2NXgLFJzTwgEh/zovApnoP6mhElkGMVXSLE+TXTSo4Q4YM9Fx2N -aJMhUco6gCwEspBK6vXzgRAYvW//HudCuX8HB7GxLgwtiGQbACcn+81ccZTrgPYJ+kflDD87iidz -C6bNq2LCjnZIBHBhDObnQ8vWs7GX0/X+1uFCAHOsUeK+mRVlwMAxIP7/kZD/W3+CAP9PQERRBgr6 -fyjYf83330Ql+9/2fwBQSwECFAMUAAAACAC7ZhZJT+TXP2QiAABjIgAADwAAAAAAAAAAAAAAtoEA -AAAA4avjpqGglI2ROTQuemlwUEsFBgAAAAABAAEAPQAAAJEiAAAAAA== ---2NqJR3m2cLnhEraiqXA4Q9hqnmihx7b7 diff --git a/tests/email_testfiles/mail_1.eml.zip b/tests/email_testfiles/mail_1.eml.zip new file mode 100644 index 0000000000000000000000000000000000000000..b01dab8111489dcba57322b9ea8cb25ba94b4b34 GIT binary patch literal 27186 zcmV(nK=Qv(O9KQH00{sH0NGV@QM1GMA9!g10Qvv{015yc0BvDuY+o@hWo>L#R0#kB z3O}}A!`Oypb$AN^0R-p+000E&0{{Ss&Ko8ReOdAE_ATmw+|0_JcEkM|OY1UZ&hC9B zcUbv&6PXp!=FALNUAW&v;U^(B{v;1c%i}F(Wdm5s;ere79`UHbSlIUOtY#-|C^)X{JA(6P^nzunrS8Ni zBoW$_XXOcN_2ZV8tD36lf(#S}4_HRdvj}wGI=Ng09?@8yj zYSp|dM z=2+$hjt3P}g{=(?p#ULVJ@ZKu8u)!O&E62etO6wbv1@RsPc#p+lA@aH5hqpQt(wys zs60*gOmy{(ClMV8B9c7hh7OalQCiYPAMpC`+?+S-^h1O9}2>7F2-N&!iDIHtniaV&S6ZES%B5DZXbB*^DIl`9 zc&G=Z#AhWZcn3kbo~$^N_b5U7YTqTPjW$AxqXuWL7gGcMaU)M?H+?ba5+q94a{~l^ zy`fx(kvN&+ zA-)TyvKXV?8%xmX=-i!#6|VsWWjP>l;(!b-&mCM-Erp-poUoJGOG1S$v`Rb~@zK0A zfyI{`!}dzUcNyIh4@h4Z^&5sIi_GU1W|r3WYz4EGg`HDfD%miHm}|axx-UihvBX%{ zLni0$MKOq)^Yqd-b-5lY6Jz|oF&&x1tj{eCpq_jZXh4?J_vzUwM=<$9DquO9OuKQ0 zyFPMisQX`@Clo+K948fJ(DUiX5NblH=jmC2%Z99?Y+pR+H3`CbD6nwX;Z0H+51ve5+pDeTiLLoDyb^+&>cG%Ckam5YTY|k}WFN zZ@oG-y?!h9rZ2`boe-g!;&$RPv||I*LI?J3C#ZaVEKWyHrzB~TjHHg?V8KTBb7UM| z-v0}~;)&L&b|}n9SsL4ygwEz8uw5d7d<}*GmjQ@KFAOfmS@gy=bD7O1{$XqWF?q*n zIqKs0-b|#vTL~7n@BXIAyOpam=g%y_NX9Y!ApYoq{SOmYap$UqQB#MKU!Kf$5ysfw zTHoOTC?Cm~w-sjq07xO$sJCcWcD8x9#*y9i&Z%>IzHF#Rgc-ai)=udm$s8u;#CL1q znSdW`R(hD`mP+Hi?S5y*+D#GCaGQB*Tj1_E65`1JvKeaP33sWo57|lXE||$b0gr6GIiu%&L!XvXQ~2qPR(tJdtU#;EhnKwf;}NX8hEhv=87y6_%Po}} zsCBZ}t@GT0c{kZUg4TTl5RSBZI5`5auAQ#r)*{Z?R-KJbsYZqRXmy+wsKn~q|Af#} z=VE%TS561sr%6pRJmBCn6&hL}$CgUtpe3Vn7~l$4YeIgcH;+a~2$8ArMiIL_H79cW zXkF%)(@KLt$shZ>NFkTE{J%)$={2sPAzO=>=p0ykHrP_b4bRLVUkUi;ml^RNn6T_h!3kLmXV$rQYTH=Sfi&kr{$ z<1fJn^~td$)zm7jgU8!a$0^L6l8TX}vs{ptAMNpft#rPzHcT&sZ?!fynU#6lkTpHj zCMn3Wu+MrqBdT+1hpaipPGF7TMA5*%E7XmvJS4zXXiZo^4Oh-S#!&DM z606_mV?ABC`w$_AX_C6&eV= zJAgp>O>KYy0Q$$DJqdb$;TZ&PNK3fXhAMkLpdPGEh7GIBjRs#MsU@!Or+m)g_+r_w zKzepP9Um66c~Q$yntYx2G1u}5_m6FnqGU}_2-O8{0*V~;$*8G;cuA1(L=@D;C_peS zpKA7e2#(x_UjdcPlsIU1xsug*@&3>jhW`U+Xgk7lp_}y_zg8qeyZclYBI9$wYl=rc@g>Xv|o>eaj>E+ z3^1;_=*yNzAbK}Bv9mG%*RsXBhS^B zrxh>Ux7iX!PYq*RhpT^rDPrlrn-zfvG-tC9uOeTCxGMG9WJ5dkWXDrv{kz2GEZ8Wy zEb$rlCgI=Zi%Bc5<+Z^ko#r_vH$D*0AWDT2s!)0^fpE^XzltsGEl`!@TkFUL#0#MV z{$`oair25pXvCU;nfNod94ba?R&Bk))Mn1;0|S(=Nz~x22qr6v*Mj9iEt_W`DZ>g%C-YONDszAXxe+9)Iy;#g{uZ zOZ();tS+_r&k2O>v1SI2=AJhlFpqx{iGYVw{x5p2b%8PAVwa$sJPJ=%Cym~5&UUAQ zEi0~kvdS*8p%M~RPUr^EKvT?}+CaL%)mb<3SG+m;3*7p>hV+|uCR7262j{w=LbTT| z{0&DiUu!KHwh%0tQXDWzaeR4=@=*8}sOtC<13FouMyYo6yz~g~BQ zR=@14(N>nxxkKbb{;p4ePtCN`&aKDMjqwPOiS%z-Cj17>f5aoc9V9b8Bs$~hc+Y#K z_SnzR8dX?B4t-NQe`2VRD7KaVhIrZsUY; z(34>Uf`vY8WD?gGR?EmebfS1xw^XwS$ZuDu(V(qHn=y8x9?wS?nbp5I2uDEdJ*Z7H@PXL%zFj4jN&VJT6gTl%yxJO$xb{?@QTnm zWuu4c()10<R>#j_VmRkq4n+iV1Po{#aQT{9z7D`b z0iB*EhahV}^ODMMNW$#Qo0$A2(2-lTE)bFbL>KC`xNFyq{uDp==KR!0ZJg#4X}Hxa z2PncKSi?*$C6(*e%ZH0_1zpw$OfvTz^&F59)yKq=sI=-%hNa|E^Z)wc!-?$C;OC3r zjM<=wiNjyo>s*z_%e7+)m>WXUhMh_F(s=JFF%&d=+lRjjnw6dx z+E=qpC`LyHiqpAbd%WH?#J6^KE05reCUjG{+udBgc7G}Pwo}Ea3Jd}sv2?!fwo=wf z4Ysm{^Rjm|uCr!oi)Ih?8#E>Ph5wYD(NMK6pqyJ>1L!Mx$^75wL(cg}7_YeD-X?ZI zZ+aX8n9+5JyH}2bt|l;Cqy!D@y&LBn9t{d9yg|jISUY`-wLwn9yT?t^ z@*Fc;ImCUkGE??F-OQJaHXJ}>+AK_Z-Q8C;#7)GzB0{b_cn~VJ_=N= zZ+o%sZ61MsIC$n&c5Vpn{}g{)|msJx{f!Gcd0Ml0?;Ki7cO zo)2!%I=}CaR-2K~V3f?nD+?Rgdw1lN+|kN<&7bDHpHp>8+o&x8fYC7qtcR^a3=Y9?1YxTC^D~$a|IYWTKS#Go6h`KxX zS8|g?5EQ`*m|{Gq&`XEmIfi&1c1(N16^`K&jJ___sdpOy_HDX|T#~888xxnmyFEhZ zT<$ai?j&I7Blx0j2OopW=4ZokYgCU1Y7Jgl?EDw%c+4fG7RB=Cw68CvnpZBycZWmAKMp4l2*^YjnlW{Iv>p^RSDS!qAX8l-~dfQ=1 zcZB5pZ$kN%c3h%OK=c_Bv8z?f(D!?R?WS+s$2UoC9uoW~juqE2HhjNLvCzT$hx%B1 zvn9tC_NQ3p+k;#^8jn#dF9z+t5f*WN?i%3&s`?V1rwTpV6zL3+8iYtr2POv>-OQpo zX<@>(#`X?x3?}TSBBj~#$bC{m_Ps-ZuT8UNPv9Wf;4&A0g-w`Y522NHeIOr-z2Poj z0?|)Tw!|S5Ck<;$nfbrfTT_^&!Nend4(j`CJk;vl4;tN89V7#Ps+Pb%<0go(;l_i8 zZwx`^mVM(0+{&5Ip`FN-JMAT$BMsA9Q2;DvT#e zSs2(#rGlY;b4~3x{ZSt$lLH4m@V!<~Wt2F@q5Iga8e*ier|V})J4YOZw_*|t9u?~Mp~RL1{=EKYL6bcuoC zZ?Jmt1@}pcAP*Ci*AUNTc`Rv-l`;$3L#^kONppNT(vZ86ivyq|S zB<%nc2bmB={kg%6Y|0p`qQf$T3_2M%340gt0zuVGeV*z*HtR~)>V_}ELM!g%ir4#%IuA@A%JIs5cSINuFo zkx2u69c`w<`#wl%0=O0P1T6VY=l?YdD|DtKx$G^nC=w<|rlimJ3H1LQWK29>zOGlA zn+yctq1ed9x0ScJ9B`2({_`K@ZrlH<%%I zcMRr19b~Cz#QeyYH27}{T|bqT%>O=iLRo`Ka^8a*qdtiC#@C_@QOTSfR*Z3>bz_Mi zv79jqRY5brTQ`HsvadzlC&x5p5k`HwnBuP>7we}uwp(2i@`wI<;|1`|L!-Mc}y_r?1D zv)E+16{Sl8s?0L4!3q^*>glfJ%txLBu)*z)b@0Kkn@cTJDW!ECsPitzecfzShDp2z zkM1<+KJ^q!n=tDRP%~L>x-Q@q8)Iz#s~?dgd8&M<=EhB>fjKwDP2V7ExQp6knmhL?-pF%nVL9% z5w1Xlx3-3|P|%ZmHPk=vCm}ArcGcdNlX4c2^!J~T-Os;US(N+?&rHNF@s~u2ezubf8~o`l=~u193@Ivz7@uG_s`0FGXXA3O5m1OIYr#dg$s-lVgO%yp5fed6}-sX(9}es`Zn0*r#`gO z%^H+|;orMsP3P~}*;!YXY~QTr)$@atX#{|*RF+OevfS9EihEpDgN();8Jr}L2j5=p zeq1_}-Wn!qhOvBS@U-VkSm7$c-*2TUKaD2f9pPVh*rDGnlj1VD6S)bdk0Xep-p`s@77}o z&4Lu;dDWXT4T?5YR(X#A_d~Acq~65Y4HXL0yr5kI)7e($iUfd`yvc=E*ClQ6=YJzu zkjfqEgzTZ9OAH-9O^5$hTu%C}IPl_BuvbX_Hy+|wgWOj! z6-4t_DA0c6<$OPeOq_tnv7-TR&(273^tQwjP;%zJ=OaSGNo0;Y{#qaB=ws$#!R$r_ z`ZU!YpUFta+q%IzgKPo(C5HxV z2^*eF_AJ#F$P(8A{_BJW(f~{&ZuXXOS+IL%R^@th-)-`rD_9%ZIh|w$TLyS9?&j(y zVpQg+v3`qo&;7yTPa4w9T|YI%HF-q~uA z5*`e;ZEuuMx&~Am^*-`=kiG9Ydv-W5F-YDZY%*UufE~@lWUaIK(KxMFzAW zpGP4Cv3MPx_TBd_86N@>wV*E!v8@XsS>>QqbzETFWX3LCB|msjT7l3xazRGpG6U#w z(6ZqdE_CFx&+F*V?jbv;Wb^FsJdZ8+Q7daVbmzolbf`7~7*IESWQ-4f=)#lC+d|vW zM{PI_QnEfA_=aXA_TJ^)%gtZp?$h`?MCi~2CDAK9R*MM- zK8=gXVHTC2P85Fth##3lqo5XJC~b7QDydkQMJ z^THvD!zDv!5S}ADZB3#J_!q^T+w$7$UWM>e7R#@i7Imikvnqnrifxh7tj3Shi7&8d z7uN!qt~6$p{K9B;?=2rzK(vzAELw#{`~8jy*oeGT-oS|qT$OO}-Mb`HfuZjWEb=I9W}=4o@A7Apj_yY!VZSaN5(6U z{M7jT30RY*eyz;_=I^3)jwMH+)W zRHnd+J5==$xo~DI#=wg@(3}YN41Vq$JRrQcUL-2w^cMxZX(x=#A&W2VEr+INb!7C? z!rDzu1-O4f0wQ9wN5MmJ_q{gH2UG+E?i6dKFe2?=)}SVOVj zb8Y2YYsNH$n|2NvR`Z~B5QiyNfEKR?v!25|v1UeQkYt^jcBUi;)Mc|>glcIJ<%`!B16IvVY<$Wir zcvj`t&92>LoeV7|$o&XeY=3Dl+Xg>xhev}<0af(7@7m8IHpg4B<9{^gerrZ`=Jf)! zcx~a~A(`pQiX!S9j@09#8~Y^}R%693mrs3h*mUw@6Gar_RlXIl$d#5bx>6vkakTrX z+B^N#j=a>$ewC?eVbev7BRQ;@WAZ2cU?ipMAhwGxSA9j(jeYjFbu!h4-<&HL`ttSS zCn<+18iHM=g%m8%|JKQi{kvNO?l0>v-Bmux)>^u0lmRFoPeS6Kh!4oC)WlCYVk0CK z9oGCBA-SP66Z~U^jGR(vZ8SePX=y}xyf_@NH*wXYxewy@u4%4)FY*$1x$*8wbD}3RAM4L z{lEX2Zwj|!Y|>B<)srwbpl?R!ycgsIcU4!zBl3&`*8b}1ym(q?7yX#qz7eVCc z!?^ID0E>Kwg>{A)>(HEvYxFwGWntlr2MTey|A-!(xJ)wZrrV^Hs3x9{emmGGV*OZC z2ddd#_2mLZ4PpPsC~{_gb0$LAJo(&0TCOVPD45ktoSLXYk^v%8^<82ArSZm(1$X2Q z^RRDvsgr z6WTzk@X-yBro&z}ty}pmcs}CMZlHH5lbT=!w-OA;B zYYO{%M&mH>RWtU_5sQGrv85GM8bVwHdZ}cEY0#BF*5Tqd$0?!|+a?p}ZEu|BN0+q$ z2tsPg()7ioM3766jFJ5Do<%~`Q~REA)TB;Hh^RS~@ZMmL@YNaTjf)4F6}DLM%f>RB z!A1-c$~dUd2aTX*p(R`wpwU}r{Ck}oai@ z<_@?&`~qdfLBUnP+FDcP6I9tW9#hF6w}{;y0cinu2u5VqXm$>J;i^<79?NsxYQYh! zNMT2#(Vc)nKLO)@jH4O6MdYlSMoItX!gmpW&~4|ZmpcUeJ|dW<@Xv(smbu0 zXCN|WF$d@vO|$&a4O!K+$_y%pY8T5@6!AE%C}7Kgw#NH!E4`gnp!W>1g=-Oj`QsLz z^qy{NxBMuSkE4=}p9h0&DAANtfj77UZ?V)XVPO?@XAj1^zR!-K>MW?yW~43S$a!Eg z1cCEquyWJJS5P;99A)WLi=GPmjKIiWKbw0&nfo{8lPYP`)jusQU=Y&MysD!e|-rp zj$PU2Z>q-3yMVX^FHD+wiVw`Aueu=0Ma;(>6zCR9nFZ>vw;oh8n567nB;V zC~qH!(x~fx3HgB=YgpnnEz_xJ0mT&F%70*u*+lIq@`s$UraT-%`MCtwGv)CHR?!2 zdJx-wYU{4qf$v{`o5=mJ*C{2D=mGp_v|fZUv$-&$9f=7IvkYk}HI=+lL_E;*RWs&d zQ=yd)Fkjd)FrW|2zjxcAJQc#%p0wF>oDJ5t(+s(=KOPu`5ZPTl@omjkR|l_!ocRoi zGAwPc8Qel^^QVDc%_st|2~5cZ|HN7gm7imC7xGJA9`=6?d9mDvdIg=pNA08^+21<9 zP=u3zVqN@qtYgN4-?o=A99AROGjV7$CcN}THyi@ok6;kZ$UA%%>NRxSxLRt_1rhrQ zIiEB!TyBxcb!ZpR*RDJ$(o?(2!O*&r9GopLYjHM+-zC3ul} zoj~NXW?!*^Rq$^iGpCFpnD9(8DjMw)n8Jz-IfEKZXm=RI?JU*HvMK>;NaLS9>BK`A_%|IG(L=$6y#j*hx+1kOZ(}$;Os!-Sgjcx+o4RqnpsF z>`TE^iPVOYWE_*SQSpJaKpbUNpD*NJhhmlVW<046=5J^09h+*0vS7Fne zN5-@0P$AJUI_#FPlC;r7*6XZq+6|A@`aTDk#Z1(_Xj-|OsH<{ny@z?S{DpNqlQ^HsTc_~C+MahKPWL6 zzVuikN-wCB#8g_A(y^%^i_{(a3?RB^Pa|^J5088dg?gE^5GH<^lQ0nGIHwPyWuKFJ*LU1yv7pw!?^=hdEXrVz#;{ zOq5A>&&Tz+Z+ex$!q@Ep^5BItiD=zE#%Xl|PjDW6^$OE>M~!gaS$S7Hw$nz-;Bh=M zp?E#k!h}lsAJuQ<1;DND$-hu@dp9NieD+8baaI^Namdq-FveQ$Mf)Uq;h&ZVp1|$1 zpMM#xHHh>1Kj=<&xW63sp$KC*igVVBpId6Bour;RW$ATQ+)GprSVL7-)3-x<>K%b& z#Jvr>nu?t3qhc{Kkn|||w{_8Lcy?&G=BQSqCU3ndqJ*~Fc}f8wtMhmVJx=Dzuba%%xmqNl_i z-Aq0|X=CarKK{ny>d>ixvBxoSIysFuF+RZR4ImSv)x)sct-!3b-2US0h4B+lgCVCl z!Wy=wxMK^Px$7E6nb_9JEJYvong-msZ1@uRKj9|QRA_`%e3jLKa%h0wfl#>EU&2-Y}WyD0UG*OtcD~?V7A%g+%OHOP}Zf6PjP9vyyWnY4|qgm zZKj0-&1uc1Bn(p7L!4Rn8|PL|Ev6DDah@$=SaIv9r6HJWjiW7tMP>qFy-L4m7lrokVE# zZis0%+1k!n&36w$v2u7YF6AFBpUrXrojPbwtE;dL9gSs@3bReK7P4N#5y=9-f}`0! z!Zo8SZh!e@(c`nq(Qfp4NbDRA9An~q=RUdptZ@fl1J|iOtYXU`ZP%jRtQ()N|DLz_ zN#WdX^$BiLEnX79t1JPIBTa=akOwC9;40YyNJ$TH;~;6iy;=T_ z+yVh2@$uVl;0Au>+B<~qW2ws26IEzQqC=!*sB#bu99N8CIpywFoCJqHheHnqoizVs zWUGDB7cy7|hH>jP2}gZ^zWM_xEjKQ2Wa$h!c%tS)jwxMAiuTyUW*$F$Mb~=^g|#x# zo58E58s2W>Hx5FqkqCz#jc>7<7#bh?qkY9saMj@&Z=Zf*;BNba*z>V(v=!rcyQn6Q z+2z|!5b~jph3+-)hs7+``d^gTj5@7~gw-LPacg`hyx26{Dc)`pSQ~BtC=VC$`#Pt{ z`Fm2-YN{0AV=Qj&ebSest%ak}5E&^uVJivk?WpX3orw2Crun9#i8T}Os507!$fSAn zby+5J$ok*Npb5;vqYI8cc?~AwW7v5jhEG{*1_uN_1#mxwR}WPP_>?XW@De$G_B^8b zy~(hP)#qVAvUcCJ*4;=r=ijA;E`bW)Jb^(8wjzb5TCUre3vzYX0F(#(i!q+QWKjTR zojrklXB?7yuB?Bptv@J?9jaG6$CEA4+-H-D*JKco?6 zvB<&wany!&f4hpqvVSR~og23`Z1W;09GHGHWGS6SCUM~$5n#rk+CQbd z;c}dk`t!1&i6O3odH)GPq95`Et5A-;;m5p5NF@NZTCzD8N11WZ)dp;v0bgG!SD+GY^rKFL2^gm{#!x8*LDY9OR_E8Zf3x>d9&f z%*ehp!4?&JcO8>0PT{+D-YBuUf@yGD_tQt4lQi`)t~Mu<-QY<#o)l6a)~UI!smj5NfPaMYA1k7m z>Mm#5rU8i#p=zP7o!lr{##UhJGLiBCT#CoL4CnVwL)VSAz7kh6@-=tdV1m`sHuN$S zon`h+#ON&G5JVjAOC|I8&vspe6lt*wz!=Oe(=WLzr3t>zqM0ejO;-y?CEg|=j?k_m zaJwq*>#Phd0*U*LR7T?#f94|w8*cPcLuaM-UYmf5y>humQ~R1}zu1U5LszYRSWEsW zu&ITvTy%4R)78pUv&j9`g5Bb@A(wmlHD0(TacBC>~&7h5HE9^92W&=HR6 zHGmKWivv9NjNKl0J!EdhHPt<_sis=EG)YY#7UxfNCoJSAvGM}J9iR;T=m`zU0|8pF z#ugWg6OCy>TT-fu1c}?f`fC!pjr}8Ih?i(8pFZ!&x&1k&x_Q=px|D>A|k_fFy=^9=z)VaYO)e1QFFRD3%4TS3oX2tJc^_d$ zJceWD57YZh`8JmFz^g#F`6e)mEx#T)<)^F>Xv3r$vsE(v@NFsp$sJEuM{x|%r@=%- zeUSyd&B52t^f83wGd!Lb!%4sktX`FYej#A~Z*bZnZmUm+O$vR2XVWi%6Bj(qQ%Q_a z$AAvXaoegGFt==?M!29(IQ^I7zAQFoNuIlg-ip@5ml>uS)Y31(Ms86&=Sc5?u@jOG zFMokxSTC4W9)UAWne*|KiMe*F%lI+wO@179g`^yWS@1S`Nq7KVRaB2N>iaTT zHl^^Q)AbM2GV$rs)XX-VFHM+jZR;sX$@lw^dDbC&;QkMBQE-bIZ7|Y)$nvC*b&?f7 zR5y$Vebe841P-%?=q)8J#W>VmXu^ zLp2cDVEKBZ7(V8`GcJud4&_AnmoI_sYt#tIs>i!ApLi{5UrlV`yiRX=Z+gXP?SO`> z>HQXH*0z;g!#&zXJPMau95*Zg>1r(RMc=|KZ)UUvwi*5HnLrU=U-^36AhsWwT%j0N z3AUJ(Y0CeALlfl;WNM^vrP|AEp&qE4>xdzH)?otg&db7U;~Uxq^rYG!tPPAUEU+v6 zpm8`uI%O?lzL4?O(!RB)A9`f))n<3zZhldNJX^hQ?`n%9Qkmc<`z}yYUsZbIeI6g( zdGGS~AZ-MFqssKq(I;;%YL2QZAXQ$qCWe2A)WSKWDXhzTf3JsC%!cXhOMjRYW2%ag zkjR8;hm`PHWJ~B=fp)S^XqIYC)4D9%-nN6r>Xz6KUysqLOg4+%Ax=5dB)Pd}FnPcj z&GeIKfL*Fjim~?9>1s}DT*)PA;n4cUGJZ4{BvA=D-1X(fLLKd%?!CU|sB|MB~>WJuw4IgtlUxXf|R^!(=$vWSDj zIW2haVA0eepAu|2SJsWjFGI04x0=?rjQWn#`!-hx%Rjd|BAW;Zyv?SAIi&!D4MkUrX)dC( z@I4VKv`pazCp}^VG5M`@3IWe8UYJn`52Tdqb;V~}urcQDaVkti;;$WuEz3jAMsSXl zA_zu%cM@LB@LRg-7GP%p@ZCB}ei^i&LHXe9^lE*Y)4u7JY01d?Qz#v6u+|Rp(gmJ5 zOtIhip=W8(I&;bSADP%3%Kw?oRS5iHrD~I6XZqJgQBfnjblHgLgL>lI z!0H*Cx&XDcdu&hRT*vZO?HC2lvs47plfmLc;iDn>yb$gL!*WpPi@LU?+{Ob|l1vJ* z-W#^*znG}}kk^t;5&Qz-(-ypy9@lNyu_Z9L{JhQujaEMI;5aXK26o0nSyaL*QtC`& z2)1x0(*gSG13{{aWU3=eI)zNI*5DGo#Y_LoE9i+(-;_!GX zFF6M-Z+foV(cZN!Lap5$i2fY)qQ(oUs#!-%oh+W3o+3|s2v&m z9=OYIM;a#5Eo z-<`%eyN5Ox2o6425OO)N0I5pf+(00N{#wUl&KNhvnGm0e>2G!DrGF6fJPBRpgF8jm zb$PTT3hBU_>GRgZoYU372`%OTP|!yJ@=*VktcRrQNi|EB#To+^bJ^fIvjlP?4RrMn ztwVW1<99gLnRXAppo=nd;z`ojcJRT_TV*3MyIPRIL@cdeVN+X0u7@eX@s3HBL(E%8 zm}`@aRV4)tNuUsm=qG{Z?QkU`I;zfE_%6;AFNeLEb)8dlE=;toi{8SQKy+R~G`Xi6Q(#AZ(g5oXs zLA-)4`O4?rU<#i6qmD(b+U}WTFQJNM0ZX5beUo_kXT}1IOBAQN^W>19=w8*RHPNJ@ zWVI=vJ)2zfF zWF<2Cl8_(!Tu?QZnR_P(_~jj~F^q;fnI;Z+(_Qi+7fBEGTqVOvxIdJ&g|^{F?!rp{ z_`SZ83qB!Q6Dw8QB@a8vX?Q%F_qXHD4?YhO#mvOFSn!J(xyFeW+}of9fOgb3JJ4KQ z&pliIF|f9ZX>K8otky|#zV%6OPU&=NAbT%t8l)_Y@Wby~FaUUg74&ByZxFCnWziR6 z4<*5cEk2R@4nZRusz)bSUyM)w`)B_aQslpnM2m7LiZ7pp_Aru%Uo$_kBi^=$Qg9>B z^p1&q50c^YAl>8)by;zOFUOl^*@FYJ&&lChVWSFnLxi%wS@LbY1!j*4gBikFp6=}3 zEp(99ftlsv>U^H!DbBnriFa4MS*IX693*7xIoQXc)BA+qE(OzG>Res1g+A#lIdP7* z>=!&O^Q5e}%Rr6Uj4*-*@EL@Dg+EDwypC8q_8C^&1FDAXHQFr7O5_mAxTZL$1MZD` z?b6RTlu=?1X0<;Cgkjnhba}71rN}QY-|?PG?DHH+`?4lPBi47g<~utzm5``=aoP3Q z%ouo0!X&riE{b%o7id@(Tal>-rI-J%t{OmM;o11EVgQj^fY>t+g-P>E9a=zsPq#rd zVA_gcf`SH0Z%+*m{NrV;r|-SG3NI0>CK;n!krfMw_WhUQgZB z9#~=(1cF?mK$q5&dJ@RhcuFVcjG=cA=ke3dVbw)srFvQg5w2$Xy;FbJCy;=Pe=V=M zehzOF#F{}s_^E<2=P;waCQ@89W!}$>*1A2G-iu|KY^mq7Uh7>Fpp~i*a&FonUeejo zOHfI+j4~pkcQH3PsG|IGfTV@o;adtjH?~A4)Qe3S)v)k--34_>=L-?A5<~)F-{}+( z_m=H%fey-am&VmClY4#o&`6OblCS~K5sFzij%h2Wdmu$koJdgHrfu)$YNA%h3=C!l zg!*fA=__yPn5m#l=sR<)Z>_Myuos@WpeEs|jC!aKutR$Y> zL`dmSuq0Lf65BiYXO=%~k(Fz)sRX*&p|qzGyzV63HZN;6JdtkinrFq>Iiae-b1f4I zLU!@-$!#jb`C2XGA*j^DVgman&^aa|ei$a^cdhGRgJk2YQir-FBC}GEi zX3@qYhvBQ#^cNMU!8apSJI!Ez!_0I|0=L*OVSPLn?GZ<}W4R?Qfab+3PD#jSqr!;f zDwq-z!87U3OUtn8#55+7*dj(bClCo^@>K8!*isqy^=(*F`gg^f#p4uG@HHlM_uv&w z<2ui%Fp@s;p*=_RxbQ6AYGfX%ooj?(pcKJ%6ga1t7;c_hDrBIdI&@qAF3z>!z1_U` zd&5pLI{pmbI&P>f+!$u+@a`&pVGnr1svUoNOP5OadQ@XrS`}A8fr||QmJ^g5^cZ;V zr3L{YU!N*v0vVY;=msk?0kj}voBI~&Zyuc85l9w|{YJ$w95nQ4ie=H*tfOU7DG#gS z-*D`j6_v_05;85Pa3-C#YM{Ri&hF-7L{%k}z~1PUbT$l-hou zJ&S5g2FVOu<+5h_@RK#K!hCj6yX&I4f=Lw16AtFBU^02&2paMP?!5Uqfty!HSoBXLjR?E{A`2CqQ&y+K;3wVEF|A8 zy6h2szD#KK8U&JXsDd9n+qy_tiG~|)dLKlqV{Hmu&QXq+|m3!poaiR%u zRpQx=*bkz}ARsC>#;g^tWni%c-KZ-3+@f3N`Wt>m$DV^lx;z)3#=}xDU>3BblZlI9 zPnE7qIY-3Dypar`PWcOIOB)2Z3>JR7hV0g28c|s(qD&7Ck0J_0MYOl$T8ZcXtSFL|i{c_}mCOc(q9>*y z_LW;G(7Q)_orPKlT@f0oq%A09lY22mzZ+VXqCJp_aM%mz0tqwvhspQ&;h){m-O-^- zrPgUUn%G0Z5Y-axJJ~JkANoa}_01Pmj-x~Lpv=o}c7lnkgfw~^{>&UAK3^O}srA7$ zF;qj0_%TSekre@|DSqixJ``rQuLsfh5C|ooYzth-R}wimy&2@M&iqV#Ta%qk66UoT zBok00f^b?j}w_$w%3l zh~%sF9)xrf!3M;Unba9Fl*b6);X~cWW}EdC3-FJQWj*F;ja-?Cgs3VX-ph2B;88~# z)q*VwBs!SfL2}azIvDvA@~x7iG&EH*ja|gsoupndt0=1-MBO3M-!P3VU`W>+z4q?= zM7}pOWXA-up=`fPhnzs8_qL2yW@+Y2(y)`nkjgwon)mrdaruf)eI=F0OqSnsT&=42 zr2|I)4r*}y9%|#k$PJ&vjf`l^B8Q+8fsV8QKfBpLM@Z;AkLY5YsCblI6?bbD9e8rw zU7o|Z{gNBFkDNjfrf9SR|IJBZ>kf6WhSWS0O%|}ek#h;+O%JI-{4ZB#w{$Df$5$*0 zKoJ}y5w%#b1g4Pf-}vCY2HBl6v>`Gi6)mBoP0WnPEA+f8w0ua6%A`44%Ewx-3UL>8 zkYpQXeQ{FIi(-wXnR?D-3Q;-h2(OTn4E49N;m7Wu4atmCgosl@rD5g zG0sHa@!%v^32(BMpBScbjdDwq;vspn?&6m|uMRZF@^=QxAgX5E2#Yid8~(tlR#8Zf zI2x3*ma-*jaRA!tFJw*Bjmh55kww_h8jy;Y-))Ju@;4YlCELP_=g(~RhYA?W0#?;u zeElGGG}~%o8VKfuS!`?cYv@A}OIn!iRQ>BFbASWLSL#0UXBX+hBdfXpSlU5e6y?DLx z{AOE50t)cV+ewp(;c#TOK-JFZs#y~#DhSPMaBI_5-x52dB>obMaVsLvn)uw=meIqa zIP@)>V0Z-4LYtH3m`!d*A-2>`2{r15250UmZ=5zAuABLPiBl0D9^q%M9y+`|5r86h zE4staHC>X=&4oN%Jzi&tw$%2cN{i4Qlh-HUIn_2T=k>$C+PAiYe>(r0ZRr{3zPA+} z6PQ#C$vl5u5t|DM28(53{5(n5t>f?eP#$gXs7NSpuO&1!O$J>HwT97W)NbB5C9-#V zyj!S*f9`2*O7)%pcB$dQGebZ+Z|9`DEl>>iNXBm8o5F@?!SAyb?z_HtmBTgDru>$ETZZv0x^K%*CW2uLvs3q2` z&%9hxR+8X65yz_=5qzBSJO!LBZD@X#lWsg*D;fp^H@{=+3P41auJi^{sG!FUZC1KU z>h88L?F}emoaAQLlYb?yrs&_vmEY}h3=G{GxQKt-1X~EjF$M8E7SVP!;*ZG~W<+S) zPNZ|A4L+M$q0OZI*a~4F7cPdDDj~|HO-_I@v9tPRH#K0aX7*#O^Uf$}CO0StRu;S2 z?AY_IQYK<2)t`H`Q6kvqd~9Yu4Blw92qAc*9K@@8Tx}9@XX$KZ&?0h?^zDEyLqztU z1k9LCaRZr5#ltL79;!qs%5!q7US9~f*(DF^0pfTUCgG^{N87ufdIgDv;-_ZFxLr*E z0rM))Y*3Qc=w=WiPuhP~WqD2~XzE(X$|vgfV3@wb6`VsAd}Zui6nRSb1J@HZIe9tp z{y7!NIl;e483=|BE}o4~)a2M0uFw4Xm&=a6+(>l?sCW}DgcAvz=Za}`cC-@Vm}Y_l zLegOKrWh&qI&6`6H>qSrqEBPlfv_eE&0{TRdpyCZsNg*`d2z~XqVMnwIEaFYQSdR5 zGowZCwM@^IO{IZi&RF(al=sCHVV>0c^dX0oq;|v_D<$gsVF_V4{yY866-k%p5lW?iP>FA_aoM|gkGRap{$!yWB^ zwdJP*=RFM?(+u}=E$Gm3}EZJvZ zl;k(>U=2WUj&7?i3X9(rSd7FS<6tino!RFi99K=Okh2{%egk3!08e4@hIfP+uZ(-$ z1lI@V7zm`!@fzF#6c%sB z;FauEU#-zKb>3QrB{|jq261%%^@~wHGt|MhY*EAERtIm`v#cv7cBa%1pa$P*#059n zPv!g8Bb%RObH>Wn=#U+AMQ`%AlX4x)8_y zpOfmhvgV_>C4;9{$A6z#Aw*3!2$@0zBsuIElWV7~^0OJfB|EB@O1&a?p3>}Vj{`C# zBcOE0eN~**ZK{r0z@g;_5^j}@1w6MpydEaXADqbez5l0VmBFQdmf=c{Pqr$A;f_K} z(#O>cDI-;+QE__A~I{l{cQBGtg=m&jUVteQ*GFuGR(?TY0S z5xbp|(v{aUDDp$esjb!{zTMO1#0btJ%pl0lcXjOL5qdFFx}+tE?vqT>)UCu`@tBEz z2yW`R!ZxIC*Mqp|EVpar{+(b*qm%80gE_kZKzEFP90A)hPB7;dc2-vZgg(fN;^uf6 zSQWm{2Lpufje^KR#G=F$t~)8;<`v>%o&Hg5`n$p2$d-=_6-;)Vqwf!B9029OG`YXV znUst-y?CO0y!@&kWT))l*lFPox!vFu%iR)_Tt4P6e~)V1iGN!L9g6U<{mjmDow*|n z>gUVa$Hr5_*1N4S@ZTt~g^m_1S%I&FBD9_F1EFQVzA;9TN#5+*L!XH9EJ_VnY-<~K z3D`QbXzaXPd86;yA7c7}@}+zTmN)a@Up4EbGQAY6KzaQnN%@RON#`*@BW}i7R~pKG z{{DDX5K;vSDSg%>T$r!#R^f(KiYpGF#Yz~MKaQ&5)LG3VK9l*Z?RL;wfM}CI4B_zu z=V3h7F2OL{@CgFzunwFz`wnxIOt&>_SVFt`F90t?_H%(Gf-U7sQZ>M;6R)v+l=xrT zd0Nj{l7M?uqH9W+)_&rjv<#EJQjB`s#39`J9LT>1*iAh87hny!>xO*+9~=(p;ck~r zy|-;?5JK0dp1l91!_oVdd;_J(52Uz$UCv{#`rYV>XXOY96-l1hfh`=i2urU=6L-Pi z{(O$hmhMrWOf4hml^7I5^=(YzN#45a@yg2jfGwANzEU@^hH+H0{u^u}rSpUR`I!vQ z;Gd$&`3NU`>w<-iER(&{jh$~5q=@KzQF1Y}VT|52KXcPp3&!B36eb|IrfbTT#ns3= zUULbI>1#{}%xeW;{$ubi&Kr;n2nzRA4}b76>jUkN2_DHCfC9SSa;4k8@4ePMJ~mE- zKRZ?@-_8_C^hb`~DEoP%z;M#9<4>oj-#`gis&p?|*r!=GOCg+g{(e&!4W_MxArfP` z@jyF3wPd>o%PO=@qXbs4!mYa(IJ&l?NaVb)K93V?#An!CXzougGNfvcB?lk8w0nG$ z?R|r~)v%ZEmcHZ^LF=G2Le@Qx4Etr2YIO#qz&F{38_?FgYdBottW+ibq@hT0F>G=v z=k8qKSyk$sa2_*XB}Vd)YYqOLRE|IIMg{{;yaQ)JuhNMYyk9bcE*Da>SFAUi5I_|! z{ONJDa*fU1F!1U@y#DC;Yct?VRfZ=fncF;!5U4L;|2hou-F5|{$Ly4QZe5m7faRXQ zAKEflF|`i2a3ay>^-a9e^Rx?YCdeA7*BSG;AahtLDmk*UOoUsR3}E`uW}WHs*bId# ziTaJF$1u&-ioLL9Q3u1Ww4s~M|8&ioSw_9F&{=o)=q`iE!?|9A^`dA=I&S>2>o7IC z#GsL_bo$sQems<$rnU`0)lm&)5$4_=hC#rsGfay1cF*_+eK5qrJXyZq0o^B{^7lyC3DFYrqlf96UF=Pwi%Y14+9w9@_;!=4AB8tB!z8 zqRfpmh2q>weHGn#^SL)VAen4?Qh`q3mpqgI7v1UkQJT9KelW1#a?GevV+gPgZ{k-| zY@~|ki%CfllbBSNPRf}`+1hjj+jWn_MxA*v69@9bWb|P%Z~;(Uxt9nK7yc+qs+&zK z<9caOC%7}>EVlsE^mAP@`WX@Rh7cBXh)u~ zBGmjnuV}}5Nb+Dr_s?==KeTNntCSMS%nxYgs*%$ntutIvwj_~(M0d=wR9X498@Sv5 zZ1V6jJ}sv4$XLV}b?l$ANkRrb>hKRg(dmXrv|`AIxpTSea*fw5YNLLr)Pa|+d`m{+ zrDcS0+{QgT;JDoz55o;|d)l;;!?#%t=IuinP3msHC$%)n6D}>j6MlxUy42NKN_`$b zyHl!C@!*|JIzB97(YN94MYgZ@1|w(41aUvTUQzCEM}R*pqkRbffcv@n%vXSjouQUEmwz6a>t5 zkDHJ|a92a5SkN+el{o>oJ6iMQCb@={>|}nXxniir6L0q3ZK~2YLGhn|q{&Q~{3H+L z3!ST+K-Sg8`DpAhS-RAUlckc&;&wwzGCE7Lh@E5#;-WpT%oV(rhAgC6uZ!kST){FX2v)iy?4*=BV0 z2?h=(Ykkz;${dhV6)sx%{&U8vbS(5~++*AYyaeU!&$JC)9j8{_}@Zi{J zq{CnZAxBBpHqrtABaMyQRu#vfZF{eMnkX(uCxcoX z&y-;E^8<0lP=)#JPk!~vl4&)tZG$`Tpgc#j7JJ9_%?#l;fYMA?i*8Q&@x+qgV00z+ z?ewRty90ADAs-lZ=p0&XKcARsMn_`x!?Y6Sk)}7{Bh~AM-Mej}1b;raQ61r^tVoAp^G0a%|oV7d$<+IFHrrLdzWYFURo!$>M>0A z=M8$Q!iko%AacAHffz+9nxv)EP}34f+x}q!LT}2QP++y*p5O8+3)D~~qnX(EQdbls zMB+1d#}J|rP=OW`2BnSDZa2h}DCrfBn;(I0tD+)u?j~{-9xi))bfcVJ_tfW;zNNSV zc2%gcP@`kdfpYxTQn4)}bFXo|bElwa`rf^Tv!&+WDuBh$(^cUUdYQ5g-B5p_j6u25 z8ZNEf1jV7a{(*V3j?B`5z3j+Hi2{<(kcNN^X&^N!dOM>KwuzPzd<*;r+Ht=T(RVPmp6=HV(4fQ_h+(ua7BWZ(nq)Kfa#Md@E z)6MY9s>lWK7BfY#Fd(G*)C_A7>t688eXw79$sM&1Q5Wdz+4B)_^PF%Y>BJ>?_~zxQA#d$rqUaTX0QdXtk*E>3|3%u=wg*5KDS_D zi2w%A&9{s8&dpS?pnOWd@%KRukc z4CA-eR%iaKW+mA`5W{K6pEli##PFnqW>L2;b%xQ&^3#rKuy5I!Izv11329aWe-B8XzNBLjg{(0`@vC;HY-X9 zG}-~=NnHqt^FR!hn;-o2!*B`Gf)Kk?IR6&rPbbHrCT5@L*56jGydqzs7J*$G0QxZI z5}12ne#TM?pn$xsX@ui8ZfCj0el-*BoJU*|>T>-4vT9mW>N{f^ws>jPFj$+@#%8%p zr1-6fpYwp0aM2w5kI5wnHcLVp;@WkBB1=Z^`nCo8^nj>f`NbG&{=S(}ZM3u%YL^sl znWZk|afQv?OUAuR^Nv*m*0UK#?%aR25(VbDeREnXIT)kk#%1^nm|MX!BSvP<_z0D; zAM-K^1h~c%xVPnoB+d~=DJXE>^4^DSBKg6Nf$&qYgx6bkNvMJKQ$e3~ zRuCtAa|t=3k2O8*Q9&xMrEX*ex!Lu?1GF@^VUftl?J%*T`THJ9g#qxMaA!J~gt}s2 zaa$eY(rRjc^vR`@RvF)jNrh~(m{qZK11K`cu`j9!Jld6Zgf61^h+dsEy!g#yme3_N z_aA!`xf(fhtE41`F4QukmPxzBXCs?~!QekNgie6bprH-aJ@fSiFj2yy83aVnzc>$O zp&+ggJ(!1bA<Kf$MG*YUTK<|hnnSr$nP{#ZiaR@evA{j;E;9%81%oSeQs#j_d5T#PIg z-W?p>1m%+B6dYFlFFA22u z&`KKmTbW;2Atx@3ssOy~3jtYv28K=KPH=RLIKw0$`@5@{5ep;VIIMmB(-7rqePw4W zDAzNA4p53ZWW^#4yON^c&?1&8uH$gzN!nQv|AGa>|5PF(4Eb!^y!3^Yba}&Td0F{t z11>xnnqazSX@OCYap6quZl}w$$4Ui(Wp!=&n8zw>kX(kFIVAqRm)9Asx1^`tyBgZb z5+N)N7g&MD@&^Y7V_`qqq{tKv_g8lM^=F=a_U9g)YgUg*(m>jIz^ zCdPYGGaj1PSz$4)gvu|oSHw*0*^g5eUsgd563e+VB6i{FUPj4b z<43NB-<#DGU*&V#3iT2#x7p;jUyAmyT*M8FqDaMiRnf22)1V=#Rs4jm1i}GF&USlC z8-ew@!CL>l4t_mg6Q}+KbyNDBH!M}33u+OfP`n$z-{i*vwXf8-mYo-@8TN*yG*Zq z$;Js;KMaM94-?}mw)QW|eXXWfpJm|xV0f!(Rf^C;$b{IQPb*pCG@d^{NiW9d?xjWb zqYi6T@up)<$Y-&ZmU2mb!Aw13oAU-b&V$olEye4lwb&+eFQB{7bz-@aCwPiHBX!^$ z5ECD8og(XTh{f&UDlkdtYxwVMz#}bxJ30wyV*ZU6+PVB7|2~MfgMLp-oDO>}P^Mp= zchw|)#t*m5`un2QWI4?m3{~bm=N9!E0aSjDNZ~e8>xud7QPYx=R9pYa+bm}w2ROg= z9^OFkU-0SDo6c4zaYto;twSi8BN(P46|8`^xW$pn(R93X5VnBIs*Fb6+;VY_Fnb?q|b?)7AtsZ_{fcwF|S}v zgRqtfk?n+}>tPAK0VVIA8k;Cqdl0*WOqf?YdjPlO)UUOkL6vehP@FS_fCvYbNL4Pn z+7##C78$Ea+kHHG-=D}8tijr8muD@8g?QwiVyto9uM3gJP{5o(e~GZs9nWNr8Q`*3 zmH5rvg(4Il@8^EqZX8vBpub8`jMNS}FYDVyi=^sY-LYnMsqNYKDURC1(+t0#m>f=k z_qjm{n%@?9gj)Hx-$xfv^VdUpMTLswWsF*M+M8}BS)Ci&aIf}ZC!!fNGg;-}bjl~u ze`+xq1Lg^S81zFCcVj@)yKw)l?bgiBLs5U6a|mVSFY0ACDtqaYz8$=O{5s zOiEkg$qhmP#u(!5;DDys$h-&i%u^qROP+Klp_^T5Ih;XQ`TC)EdOc16FfU@pzrz2u zW%u&X+wkh0)1O7bXsvK#iO6$7W1pqwme!|%K62Zy+Tm6uFAe$Ue-oSJrGY{4LH~a= vCrqIKS-}78rhxzH{x{nR{Qt6@{vWQByfiq(|J(%rujKzbr~V^D0RjCVEvdzV literal 0 HcmV?d00001 diff --git a/tests/test_emailobject.py b/tests/test_emailobject.py index 64f57c8..dce618d 100644 --- a/tests/test_emailobject.py +++ b/tests/test_emailobject.py @@ -1,17 +1,27 @@ -from email.message import EmailMessage -import unittest -from io import BytesIO -from typing import List -from pymisp.tools import EMailObject -from pathlib import Path -from os import urandom import json +import unittest + +from email.message import EmailMessage +from io import BytesIO +from os import urandom +from pathlib import Path +from typing import List +from zipfile import ZipFile + +from pymisp.tools import EMailObject from pymisp.exceptions import PyMISPNotImplementedYet, InvalidMISPObject class TestEmailObject(unittest.TestCase): + + @classmethod + def setUpClass(cls): + with ZipFile(Path("tests/email_testfiles/mail_1.eml.zip"), 'r') as myzip: + with myzip.open('mail_1.eml', pwd=b'AVs are dumb') as myfile: + cls.eml_1 = BytesIO(myfile.read()) + def test_mail_1(self): - email_object = EMailObject(Path("tests/email_testfiles/mail_1.eml")) + email_object = EMailObject(pseudofile=self.eml_1) self.assertEqual(self._get_values(email_object, "subject")[0], "письмо уведом-е") self.assertEqual(self._get_values(email_object, "to")[0], "kinney@noth.com") self.assertEqual(self._get_values(email_object, "from")[0], "suvorov.s@nalg.ru") @@ -50,7 +60,7 @@ class TestEmailObject(unittest.TestCase): def test_msg(self): # Test result of eml converted to msg is the same - eml_email_object = EMailObject(Path("tests/email_testfiles/mail_1.eml")) + eml_email_object = EMailObject(pseudofile=self.eml_1) email_object = EMailObject(Path("tests/email_testfiles/mail_1.msg")) self.assertIsInstance(email_object.email, EmailMessage) @@ -74,7 +84,7 @@ class TestEmailObject(unittest.TestCase): def test_bom_encoded(self): """Test utf-8-sig encoded email""" bom_email_object = EMailObject(Path("tests/email_testfiles/mail_1_bom.eml")) - eml_email_object = EMailObject(Path("tests/email_testfiles/mail_1.eml")) + eml_email_object = EMailObject(pseudofile=self.eml_1) self.assertIsInstance(bom_email_object.email, EmailMessage) for file_name, file_content in bom_email_object.attachments: From 6f6784ba885b7208a9dea751bcba47a1d96cf2da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Vinot?= Date: Thu, 4 Jan 2024 13:37:24 +0100 Subject: [PATCH 21/80] chg: remove jsonschema from dependencies --- CHANGELOG.txt | 14 + poetry.lock | 634 +++++++++++++++++++++++--------------------- pymisp/mispevent.py | 9 +- pyproject.toml | 7 +- 4 files changed, 346 insertions(+), 318 deletions(-) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index f09ba64..5bf234e 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -7,6 +7,7 @@ v2.4.182 (2023-12-14) Changes ~~~~~~~ +- Bump changelog. [Raphaël Vinot] - Bump version. [Raphaël Vinot] - Bump objects. [Raphaël Vinot] - Bump deps. [Raphaël Vinot] @@ -21,6 +22,19 @@ Fix Other ~~~~~ +- Build(deps): bump github/codeql-action from 2 to 3. [dependabot[bot]] + + Bumps [github/codeql-action](https://github.com/github/codeql-action) from 2 to 3. + - [Release notes](https://github.com/github/codeql-action/releases) + - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) + - [Commits](https://github.com/github/codeql-action/compare/v2...v3) + + --- + updated-dependencies: + - dependency-name: github/codeql-action + dependency-type: direct:production + update-type: version-update:semver-major + ... - Build(deps): bump actions/setup-python from 4 to 5. [dependabot[bot]] Bumps [actions/setup-python](https://github.com/actions/setup-python) from 4 to 5. diff --git a/poetry.lock b/poetry.lock index 8e748f8..7cf0ed1 100644 --- a/poetry.lock +++ b/poetry.lock @@ -13,19 +13,20 @@ files = [ [[package]] name = "anyio" -version = "4.1.0" +version = "4.2.0" description = "High level compatibility layer for multiple asynchronous event loop implementations" optional = false python-versions = ">=3.8" files = [ - {file = "anyio-4.1.0-py3-none-any.whl", hash = "sha256:56a415fbc462291813a94528a779597226619c8e78af7de0507333f700011e5f"}, - {file = "anyio-4.1.0.tar.gz", hash = "sha256:5a0bec7085176715be77df87fc66d6c9d70626bd752fcc85f57cdbee5b3760da"}, + {file = "anyio-4.2.0-py3-none-any.whl", hash = "sha256:745843b39e829e108e518c489b31dc757de7d2131d53fac32bd8df268227bfee"}, + {file = "anyio-4.2.0.tar.gz", hash = "sha256:e1875bb4b4e2de1669f4bc7869b6d3f54231cdced71605e6e64c9be77e3be50f"}, ] [package.dependencies] exceptiongroup = {version = ">=1.0.2", markers = "python_version < \"3.11\""} idna = ">=2.8" sniffio = ">=1.1" +typing-extensions = {version = ">=4.1", markers = "python_version < \"3.11\""} [package.extras] doc = ["Sphinx (>=7)", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx-rtd-theme"] @@ -153,21 +154,22 @@ typing-extensions = {version = ">=4.0.0", markers = "python_version < \"3.11\""} [[package]] name = "attrs" -version = "23.1.0" +version = "23.2.0" description = "Classes Without Boilerplate" optional = false python-versions = ">=3.7" files = [ - {file = "attrs-23.1.0-py3-none-any.whl", hash = "sha256:1f28b4522cdc2fb4256ac1a020c78acf9cba2c6b461ccd2c126f3aa8e8335d04"}, - {file = "attrs-23.1.0.tar.gz", hash = "sha256:6279836d581513a26f1bf235f9acd333bc9115683f14f7e8fae46c98fc50e015"}, + {file = "attrs-23.2.0-py3-none-any.whl", hash = "sha256:99b87a485a5820b23b879f04c2305b44b951b502fd64be915879d77a7e8fc6f1"}, + {file = "attrs-23.2.0.tar.gz", hash = "sha256:935dc3b529c262f6cf76e50877d35a4bd3c1de194fd41f47a2b7ae8f19971f30"}, ] [package.extras] cov = ["attrs[tests]", "coverage[toml] (>=5.3)"] -dev = ["attrs[docs,tests]", "pre-commit"] +dev = ["attrs[tests]", "pre-commit"] docs = ["furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier", "zope-interface"] tests = ["attrs[tests-no-zope]", "zope-interface"] -tests-no-zope = ["cloudpickle", "hypothesis", "mypy (>=1.1.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] +tests-mypy = ["mypy (>=1.6)", "pytest-mypy-plugins"] +tests-no-zope = ["attrs[tests-mypy]", "cloudpickle", "hypothesis", "pympler", "pytest (>=4.3.0)", "pytest-xdist[psutil]"] [[package]] name = "babel" @@ -601,13 +603,13 @@ files = [ [[package]] name = "comm" -version = "0.2.0" +version = "0.2.1" description = "Jupyter Python Comm implementation, for usage in ipykernel, xeus-python etc." optional = false python-versions = ">=3.8" files = [ - {file = "comm-0.2.0-py3-none-any.whl", hash = "sha256:2da8d9ebb8dd7bfc247adaff99f24dce705638a8042b85cb995066793e391001"}, - {file = "comm-0.2.0.tar.gz", hash = "sha256:a517ea2ca28931c7007a7a99c562a0fa5883cfb48963140cf642c41c948498be"}, + {file = "comm-0.2.1-py3-none-any.whl", hash = "sha256:87928485c0dfc0e7976fd89fc1e187023cf587e7c353e4a9b417555b44adf021"}, + {file = "comm-0.2.1.tar.gz", hash = "sha256:0bc91edae1344d39d3661dcbc36937181fdaddb304790458f8b044dbc064b89a"}, ] [package.dependencies] @@ -642,63 +644,63 @@ files = [ [[package]] name = "coverage" -version = "7.3.2" +version = "7.4.0" description = "Code coverage measurement for Python" optional = false python-versions = ">=3.8" files = [ - {file = "coverage-7.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d872145f3a3231a5f20fd48500274d7df222e291d90baa2026cc5152b7ce86bf"}, - {file = "coverage-7.3.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:310b3bb9c91ea66d59c53fa4989f57d2436e08f18fb2f421a1b0b6b8cc7fffda"}, - {file = "coverage-7.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f47d39359e2c3779c5331fc740cf4bce6d9d680a7b4b4ead97056a0ae07cb49a"}, - {file = "coverage-7.3.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:aa72dbaf2c2068404b9870d93436e6d23addd8bbe9295f49cbca83f6e278179c"}, - {file = "coverage-7.3.2-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:beaa5c1b4777f03fc63dfd2a6bd820f73f036bfb10e925fce067b00a340d0f3f"}, - {file = "coverage-7.3.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:dbc1b46b92186cc8074fee9d9fbb97a9dd06c6cbbef391c2f59d80eabdf0faa6"}, - {file = "coverage-7.3.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:315a989e861031334d7bee1f9113c8770472db2ac484e5b8c3173428360a9148"}, - {file = "coverage-7.3.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:d1bc430677773397f64a5c88cb522ea43175ff16f8bfcc89d467d974cb2274f9"}, - {file = "coverage-7.3.2-cp310-cp310-win32.whl", hash = "sha256:a889ae02f43aa45032afe364c8ae84ad3c54828c2faa44f3bfcafecb5c96b02f"}, - {file = "coverage-7.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:c0ba320de3fb8c6ec16e0be17ee1d3d69adcda99406c43c0409cb5c41788a611"}, - {file = "coverage-7.3.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ac8c802fa29843a72d32ec56d0ca792ad15a302b28ca6203389afe21f8fa062c"}, - {file = "coverage-7.3.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:89a937174104339e3a3ffcf9f446c00e3a806c28b1841c63edb2b369310fd074"}, - {file = "coverage-7.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e267e9e2b574a176ddb983399dec325a80dbe161f1a32715c780b5d14b5f583a"}, - {file = "coverage-7.3.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2443cbda35df0d35dcfb9bf8f3c02c57c1d6111169e3c85fc1fcc05e0c9f39a3"}, - {file = "coverage-7.3.2-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4175e10cc8dda0265653e8714b3174430b07c1dca8957f4966cbd6c2b1b8065a"}, - {file = "coverage-7.3.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:0cbf38419fb1a347aaf63481c00f0bdc86889d9fbf3f25109cf96c26b403fda1"}, - {file = "coverage-7.3.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:5c913b556a116b8d5f6ef834038ba983834d887d82187c8f73dec21049abd65c"}, - {file = "coverage-7.3.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:1981f785239e4e39e6444c63a98da3a1db8e971cb9ceb50a945ba6296b43f312"}, - {file = "coverage-7.3.2-cp311-cp311-win32.whl", hash = "sha256:43668cabd5ca8258f5954f27a3aaf78757e6acf13c17604d89648ecc0cc66640"}, - {file = "coverage-7.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:e10c39c0452bf6e694511c901426d6b5ac005acc0f78ff265dbe36bf81f808a2"}, - {file = "coverage-7.3.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:4cbae1051ab791debecc4a5dcc4a1ff45fc27b91b9aee165c8a27514dd160836"}, - {file = "coverage-7.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:12d15ab5833a997716d76f2ac1e4b4d536814fc213c85ca72756c19e5a6b3d63"}, - {file = "coverage-7.3.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3c7bba973ebee5e56fe9251300c00f1579652587a9f4a5ed8404b15a0471f216"}, - {file = "coverage-7.3.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fe494faa90ce6381770746077243231e0b83ff3f17069d748f645617cefe19d4"}, - {file = "coverage-7.3.2-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f6e9589bd04d0461a417562649522575d8752904d35c12907d8c9dfeba588faf"}, - {file = "coverage-7.3.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d51ac2a26f71da1b57f2dc81d0e108b6ab177e7d30e774db90675467c847bbdf"}, - {file = "coverage-7.3.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:99b89d9f76070237975b315b3d5f4d6956ae354a4c92ac2388a5695516e47c84"}, - {file = "coverage-7.3.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:fa28e909776dc69efb6ed975a63691bc8172b64ff357e663a1bb06ff3c9b589a"}, - {file = "coverage-7.3.2-cp312-cp312-win32.whl", hash = "sha256:289fe43bf45a575e3ab10b26d7b6f2ddb9ee2dba447499f5401cfb5ecb8196bb"}, - {file = "coverage-7.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:7dbc3ed60e8659bc59b6b304b43ff9c3ed858da2839c78b804973f613d3e92ed"}, - {file = "coverage-7.3.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:f94b734214ea6a36fe16e96a70d941af80ff3bfd716c141300d95ebc85339738"}, - {file = "coverage-7.3.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:af3d828d2c1cbae52d34bdbb22fcd94d1ce715d95f1a012354a75e5913f1bda2"}, - {file = "coverage-7.3.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:630b13e3036e13c7adc480ca42fa7afc2a5d938081d28e20903cf7fd687872e2"}, - {file = "coverage-7.3.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c9eacf273e885b02a0273bb3a2170f30e2d53a6d53b72dbe02d6701b5296101c"}, - {file = "coverage-7.3.2-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d8f17966e861ff97305e0801134e69db33b143bbfb36436efb9cfff6ec7b2fd9"}, - {file = "coverage-7.3.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:b4275802d16882cf9c8b3d057a0839acb07ee9379fa2749eca54efbce1535b82"}, - {file = "coverage-7.3.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:72c0cfa5250f483181e677ebc97133ea1ab3eb68645e494775deb6a7f6f83901"}, - {file = "coverage-7.3.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:cb536f0dcd14149425996821a168f6e269d7dcd2c273a8bff8201e79f5104e76"}, - {file = "coverage-7.3.2-cp38-cp38-win32.whl", hash = "sha256:307adb8bd3abe389a471e649038a71b4eb13bfd6b7dd9a129fa856f5c695cf92"}, - {file = "coverage-7.3.2-cp38-cp38-win_amd64.whl", hash = "sha256:88ed2c30a49ea81ea3b7f172e0269c182a44c236eb394718f976239892c0a27a"}, - {file = "coverage-7.3.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b631c92dfe601adf8f5ebc7fc13ced6bb6e9609b19d9a8cd59fa47c4186ad1ce"}, - {file = "coverage-7.3.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:d3d9df4051c4a7d13036524b66ecf7a7537d14c18a384043f30a303b146164e9"}, - {file = "coverage-7.3.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5f7363d3b6a1119ef05015959ca24a9afc0ea8a02c687fe7e2d557705375c01f"}, - {file = "coverage-7.3.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2f11cc3c967a09d3695d2a6f03fb3e6236622b93be7a4b5dc09166a861be6d25"}, - {file = "coverage-7.3.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:149de1d2401ae4655c436a3dced6dd153f4c3309f599c3d4bd97ab172eaf02d9"}, - {file = "coverage-7.3.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:3a4006916aa6fee7cd38db3bfc95aa9c54ebb4ffbfc47c677c8bba949ceba0a6"}, - {file = "coverage-7.3.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9028a3871280110d6e1aa2df1afd5ef003bab5fb1ef421d6dc748ae1c8ef2ebc"}, - {file = "coverage-7.3.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:9f805d62aec8eb92bab5b61c0f07329275b6f41c97d80e847b03eb894f38d083"}, - {file = "coverage-7.3.2-cp39-cp39-win32.whl", hash = "sha256:d1c88ec1a7ff4ebca0219f5b1ef863451d828cccf889c173e1253aa84b1e07ce"}, - {file = "coverage-7.3.2-cp39-cp39-win_amd64.whl", hash = "sha256:b4767da59464bb593c07afceaddea61b154136300881844768037fd5e859353f"}, - {file = "coverage-7.3.2-pp38.pp39.pp310-none-any.whl", hash = "sha256:ae97af89f0fbf373400970c0a21eef5aa941ffeed90aee43650b81f7d7f47637"}, - {file = "coverage-7.3.2.tar.gz", hash = "sha256:be32ad29341b0170e795ca590e1c07e81fc061cb5b10c74ce7203491484404ef"}, + {file = "coverage-7.4.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:36b0ea8ab20d6a7564e89cb6135920bc9188fb5f1f7152e94e8300b7b189441a"}, + {file = "coverage-7.4.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0676cd0ba581e514b7f726495ea75aba3eb20899d824636c6f59b0ed2f88c471"}, + {file = "coverage-7.4.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d0ca5c71a5a1765a0f8f88022c52b6b8be740e512980362f7fdbb03725a0d6b9"}, + {file = "coverage-7.4.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a7c97726520f784239f6c62506bc70e48d01ae71e9da128259d61ca5e9788516"}, + {file = "coverage-7.4.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:815ac2d0f3398a14286dc2cea223a6f338109f9ecf39a71160cd1628786bc6f5"}, + {file = "coverage-7.4.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:80b5ee39b7f0131ebec7968baa9b2309eddb35b8403d1869e08f024efd883566"}, + {file = "coverage-7.4.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:5b2ccb7548a0b65974860a78c9ffe1173cfb5877460e5a229238d985565574ae"}, + {file = "coverage-7.4.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:995ea5c48c4ebfd898eacb098164b3cc826ba273b3049e4a889658548e321b43"}, + {file = "coverage-7.4.0-cp310-cp310-win32.whl", hash = "sha256:79287fd95585ed36e83182794a57a46aeae0b64ca53929d1176db56aacc83451"}, + {file = "coverage-7.4.0-cp310-cp310-win_amd64.whl", hash = "sha256:5b14b4f8760006bfdb6e08667af7bc2d8d9bfdb648351915315ea17645347137"}, + {file = "coverage-7.4.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:04387a4a6ecb330c1878907ce0dc04078ea72a869263e53c72a1ba5bbdf380ca"}, + {file = "coverage-7.4.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ea81d8f9691bb53f4fb4db603203029643caffc82bf998ab5b59ca05560f4c06"}, + {file = "coverage-7.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:74775198b702868ec2d058cb92720a3c5a9177296f75bd97317c787daf711505"}, + {file = "coverage-7.4.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:76f03940f9973bfaee8cfba70ac991825611b9aac047e5c80d499a44079ec0bc"}, + {file = "coverage-7.4.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:485e9f897cf4856a65a57c7f6ea3dc0d4e6c076c87311d4bc003f82cfe199d25"}, + {file = "coverage-7.4.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:6ae8c9d301207e6856865867d762a4b6fd379c714fcc0607a84b92ee63feff70"}, + {file = "coverage-7.4.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:bf477c355274a72435ceb140dc42de0dc1e1e0bf6e97195be30487d8eaaf1a09"}, + {file = "coverage-7.4.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:83c2dda2666fe32332f8e87481eed056c8b4d163fe18ecc690b02802d36a4d26"}, + {file = "coverage-7.4.0-cp311-cp311-win32.whl", hash = "sha256:697d1317e5290a313ef0d369650cfee1a114abb6021fa239ca12b4849ebbd614"}, + {file = "coverage-7.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:26776ff6c711d9d835557ee453082025d871e30b3fd6c27fcef14733f67f0590"}, + {file = "coverage-7.4.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:13eaf476ec3e883fe3e5fe3707caeb88268a06284484a3daf8250259ef1ba143"}, + {file = "coverage-7.4.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:846f52f46e212affb5bcf131c952fb4075b55aae6b61adc9856222df89cbe3e2"}, + {file = "coverage-7.4.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:26f66da8695719ccf90e794ed567a1549bb2644a706b41e9f6eae6816b398c4a"}, + {file = "coverage-7.4.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:164fdcc3246c69a6526a59b744b62e303039a81e42cfbbdc171c91a8cc2f9446"}, + {file = "coverage-7.4.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:316543f71025a6565677d84bc4df2114e9b6a615aa39fb165d697dba06a54af9"}, + {file = "coverage-7.4.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:bb1de682da0b824411e00a0d4da5a784ec6496b6850fdf8c865c1d68c0e318dd"}, + {file = "coverage-7.4.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:0e8d06778e8fbffccfe96331a3946237f87b1e1d359d7fbe8b06b96c95a5407a"}, + {file = "coverage-7.4.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:a56de34db7b7ff77056a37aedded01b2b98b508227d2d0979d373a9b5d353daa"}, + {file = "coverage-7.4.0-cp312-cp312-win32.whl", hash = "sha256:51456e6fa099a8d9d91497202d9563a320513fcf59f33991b0661a4a6f2ad450"}, + {file = "coverage-7.4.0-cp312-cp312-win_amd64.whl", hash = "sha256:cd3c1e4cb2ff0083758f09be0f77402e1bdf704adb7f89108007300a6da587d0"}, + {file = "coverage-7.4.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:e9d1bf53c4c8de58d22e0e956a79a5b37f754ed1ffdbf1a260d9dcfa2d8a325e"}, + {file = "coverage-7.4.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:109f5985182b6b81fe33323ab4707011875198c41964f014579cf82cebf2bb85"}, + {file = "coverage-7.4.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3cc9d4bc55de8003663ec94c2f215d12d42ceea128da8f0f4036235a119c88ac"}, + {file = "coverage-7.4.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cc6d65b21c219ec2072c1293c505cf36e4e913a3f936d80028993dd73c7906b1"}, + {file = "coverage-7.4.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5a10a4920def78bbfff4eff8a05c51be03e42f1c3735be42d851f199144897ba"}, + {file = "coverage-7.4.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:b8e99f06160602bc64da35158bb76c73522a4010f0649be44a4e167ff8555952"}, + {file = "coverage-7.4.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:7d360587e64d006402b7116623cebf9d48893329ef035278969fa3bbf75b697e"}, + {file = "coverage-7.4.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:29f3abe810930311c0b5d1a7140f6395369c3db1be68345638c33eec07535105"}, + {file = "coverage-7.4.0-cp38-cp38-win32.whl", hash = "sha256:5040148f4ec43644702e7b16ca864c5314ccb8ee0751ef617d49aa0e2d6bf4f2"}, + {file = "coverage-7.4.0-cp38-cp38-win_amd64.whl", hash = "sha256:9864463c1c2f9cb3b5db2cf1ff475eed2f0b4285c2aaf4d357b69959941aa555"}, + {file = "coverage-7.4.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:936d38794044b26c99d3dd004d8af0035ac535b92090f7f2bb5aa9c8e2f5cd42"}, + {file = "coverage-7.4.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:799c8f873794a08cdf216aa5d0531c6a3747793b70c53f70e98259720a6fe2d7"}, + {file = "coverage-7.4.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e7defbb9737274023e2d7af02cac77043c86ce88a907c58f42b580a97d5bcca9"}, + {file = "coverage-7.4.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a1526d265743fb49363974b7aa8d5899ff64ee07df47dd8d3e37dcc0818f09ed"}, + {file = "coverage-7.4.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bf635a52fc1ea401baf88843ae8708591aa4adff875e5c23220de43b1ccf575c"}, + {file = "coverage-7.4.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:756ded44f47f330666843b5781be126ab57bb57c22adbb07d83f6b519783b870"}, + {file = "coverage-7.4.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:0eb3c2f32dabe3a4aaf6441dde94f35687224dfd7eb2a7f47f3fd9428e421058"}, + {file = "coverage-7.4.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:bfd5db349d15c08311702611f3dccbef4b4e2ec148fcc636cf8739519b4a5c0f"}, + {file = "coverage-7.4.0-cp39-cp39-win32.whl", hash = "sha256:53d7d9158ee03956e0eadac38dfa1ec8068431ef8058fe6447043db1fb40d932"}, + {file = "coverage-7.4.0-cp39-cp39-win_amd64.whl", hash = "sha256:cfd2a8b6b0d8e66e944d47cdec2f47c48fef2ba2f2dff5a9a75757f64172857e"}, + {file = "coverage-7.4.0-pp38.pp39.pp310-none-any.whl", hash = "sha256:c530833afc4707fe48524a44844493f36d8727f04dcce91fb978c414a8556cc6"}, + {file = "coverage-7.4.0.tar.gz", hash = "sha256:707c0f58cb1712b8809ece32b68996ee1e609f71bd14615bd8f87a1293cb610e"}, ] [package.dependencies] @@ -907,13 +909,13 @@ readthedocs = ["sphinx-rtd-theme"] [[package]] name = "fastjsonschema" -version = "2.19.0" +version = "2.19.1" description = "Fastest Python implementation of JSON schema" optional = false python-versions = "*" files = [ - {file = "fastjsonschema-2.19.0-py3-none-any.whl", hash = "sha256:b9fd1a2dd6971dbc7fee280a95bd199ae0dd9ce22beb91cc75e9c1c528a5170e"}, - {file = "fastjsonschema-2.19.0.tar.gz", hash = "sha256:e25df6647e1bc4a26070b700897b07b542ec898dd4f1f6ea013e7f6a88417225"}, + {file = "fastjsonschema-2.19.1-py3-none-any.whl", hash = "sha256:3672b47bc94178c9f23dbb654bf47440155d4db9df5f7bc47643315f9c405cd0"}, + {file = "fastjsonschema-2.19.1.tar.gz", hash = "sha256:e3126a94bdc4623d3de4485f8d468a12f02a67921315ddc87836d6e456dc789d"}, ] [package.extras] @@ -954,13 +956,13 @@ files = [ [[package]] name = "importlib-metadata" -version = "7.0.0" +version = "7.0.1" description = "Read metadata from Python packages" optional = false python-versions = ">=3.8" files = [ - {file = "importlib_metadata-7.0.0-py3-none-any.whl", hash = "sha256:d97503976bb81f40a193d41ee6570868479c69d5068651eb039c40d850c59d67"}, - {file = "importlib_metadata-7.0.0.tar.gz", hash = "sha256:7fc841f8b8332803464e5dc1c63a2e59121f46ca186c0e2e182e80bf8c1319f7"}, + {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] @@ -1002,13 +1004,13 @@ files = [ [[package]] name = "ipykernel" -version = "6.27.1" +version = "6.28.0" description = "IPython Kernel for Jupyter" optional = false python-versions = ">=3.8" files = [ - {file = "ipykernel-6.27.1-py3-none-any.whl", hash = "sha256:dab88b47f112f9f7df62236511023c9bdeef67abc73af7c652e4ce4441601686"}, - {file = "ipykernel-6.27.1.tar.gz", hash = "sha256:7d5d594b6690654b4d299edba5e872dc17bb7396a8d0609c97cb7b8a1c605de6"}, + {file = "ipykernel-6.28.0-py3-none-any.whl", hash = "sha256:c6e9a9c63a7f4095c0a22a79f765f079f9ec7be4f2430a898ddea889e8665661"}, + {file = "ipykernel-6.28.0.tar.gz", hash = "sha256:69c11403d26de69df02225916f916b37ea4b9af417da0a8c827f84328d88e5f3"}, ] [package.dependencies] @@ -1022,7 +1024,7 @@ matplotlib-inline = ">=0.1" nest-asyncio = "*" packaging = "*" psutil = "*" -pyzmq = ">=20" +pyzmq = ">=24" tornado = ">=6.1" traitlets = ">=5.4.0" @@ -1216,13 +1218,13 @@ format-nongpl = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339- [[package]] name = "jsonschema-specifications" -version = "2023.11.2" +version = "2023.12.1" description = "The JSON Schema meta-schemas and vocabularies, exposed as a Registry" optional = false python-versions = ">=3.8" files = [ - {file = "jsonschema_specifications-2023.11.2-py3-none-any.whl", hash = "sha256:e74ba7c0a65e8cb49dc26837d6cfe576557084a8b423ed16a420984228104f93"}, - {file = "jsonschema_specifications-2023.11.2.tar.gz", hash = "sha256:9472fc4fea474cd74bea4a2b190daeccb5a9e4db2ea80efcf7a1b582fc9a81b8"}, + {file = "jsonschema_specifications-2023.12.1-py3-none-any.whl", hash = "sha256:87e4fdf3a94858b8a2ba2778d9ba57d8a9cafca7c7489c46ba0d30a8bc6a9c3c"}, + {file = "jsonschema_specifications-2023.12.1.tar.gz", hash = "sha256:48a76787b3e70f5ed53f1160d2b81f586e4ca6d1548c5de7085d1682674764cc"}, ] [package.dependencies] @@ -1254,13 +1256,13 @@ test = ["coverage", "ipykernel (>=6.14)", "mypy", "paramiko", "pre-commit", "pyt [[package]] name = "jupyter-core" -version = "5.5.0" +version = "5.7.0" description = "Jupyter core package. A base package on which Jupyter projects rely." optional = false python-versions = ">=3.8" files = [ - {file = "jupyter_core-5.5.0-py3-none-any.whl", hash = "sha256:e11e02cd8ae0a9de5c6c44abf5727df9f2581055afe00b22183f621ba3585805"}, - {file = "jupyter_core-5.5.0.tar.gz", hash = "sha256:880b86053bf298a8724994f95e99b99130659022a4f7f45f563084b6223861d3"}, + {file = "jupyter_core-5.7.0-py3-none-any.whl", hash = "sha256:16eea462f7dad23ba9f86542bdf17f830804e2028eb48d609b6134d91681e983"}, + {file = "jupyter_core-5.7.0.tar.gz", hash = "sha256:cb8d3ed92144d2463a3c5664fdd686a3f0c1442ea45df8babb1c1a9e6333fe03"}, ] [package.dependencies] @@ -1314,13 +1316,13 @@ jupyter-server = ">=1.1.2" [[package]] name = "jupyter-server" -version = "2.12.1" +version = "2.12.2" description = "The backend—i.e. core services, APIs, and REST endpoints—to Jupyter web applications." optional = false python-versions = ">=3.8" files = [ - {file = "jupyter_server-2.12.1-py3-none-any.whl", hash = "sha256:fd030dd7be1ca572e4598203f718df6630c12bd28a599d7f1791c4d7938e1010"}, - {file = "jupyter_server-2.12.1.tar.gz", hash = "sha256:dc77b7dcc5fc0547acba2b2844f01798008667201eea27c6319ff9257d700a6d"}, + {file = "jupyter_server-2.12.2-py3-none-any.whl", hash = "sha256:abcfa33f98a959f908c8733aa2d9fa0101d26941cbd49b148f4cef4d3046fc61"}, + {file = "jupyter_server-2.12.2.tar.gz", hash = "sha256:5eae86be15224b5375cdec0c3542ce72ff20f7a25297a2a8166a250bb455a519"}, ] [package.dependencies] @@ -1350,13 +1352,13 @@ test = ["flaky", "ipykernel", "pre-commit", "pytest (>=7.0)", "pytest-console-sc [[package]] name = "jupyter-server-terminals" -version = "0.5.0" +version = "0.5.1" description = "A Jupyter Server Extension Providing Terminals." optional = false python-versions = ">=3.8" files = [ - {file = "jupyter_server_terminals-0.5.0-py3-none-any.whl", hash = "sha256:2fc0692c883bfd891f4fba0c4b4a684a37234b0ba472f2e97ed0a3888f46e1e4"}, - {file = "jupyter_server_terminals-0.5.0.tar.gz", hash = "sha256:ebcd68c9afbf98a480a533e6f3266354336e645536953b7abcc7bdeebc0154a3"}, + {file = "jupyter_server_terminals-0.5.1-py3-none-any.whl", hash = "sha256:5e63e947ddd97bb2832db5ef837a258d9ccd4192cd608c1270850ad947ae5dd7"}, + {file = "jupyter_server_terminals-0.5.1.tar.gz", hash = "sha256:16d3be9cf48be6a1f943f3a6c93c033be259cf4779184c66421709cf63dccfea"}, ] [package.dependencies] @@ -1369,13 +1371,13 @@ test = ["jupyter-server (>=2.0.0)", "pytest (>=7.0)", "pytest-jupyter[server] (> [[package]] name = "jupyterlab" -version = "4.0.9" +version = "4.0.10" description = "JupyterLab computational environment" optional = false python-versions = ">=3.8" files = [ - {file = "jupyterlab-4.0.9-py3-none-any.whl", hash = "sha256:9f6f8e36d543fdbcc3df961a1d6a3f524b4a4001be0327a398f68fa4e534107c"}, - {file = "jupyterlab-4.0.9.tar.gz", hash = "sha256:9ebada41d52651f623c0c9f069ddb8a21d6848e4c887d8e5ddc0613166ed5c0b"}, + {file = "jupyterlab-4.0.10-py3-none-any.whl", hash = "sha256:fe010ad9e37017488b468632ef2ead255fc7c671c5b64d9ca13e1f7b7e665c37"}, + {file = "jupyterlab-4.0.10.tar.gz", hash = "sha256:46177eb8ede70dc73be922ac99f8ef943bdc2dfbc6a31b353c4bde848a35dee1"}, ] [package.dependencies] @@ -1395,7 +1397,7 @@ tornado = ">=6.2.0" traitlets = "*" [package.extras] -dev = ["black[jupyter] (==23.10.1)", "build", "bump2version", "coverage", "hatch", "pre-commit", "pytest-cov", "ruff (==0.1.4)"] +dev = ["build", "bump2version", "coverage", "hatch", "pre-commit", "pytest-cov", "ruff (==0.1.6)"] docs = ["jsx-lexer", "myst-parser", "pydata-sphinx-theme (>=0.13.0)", "pytest", "pytest-check-links", "pytest-tornasync", "sphinx (>=1.8,<7.2.0)", "sphinx-copybutton"] docs-screenshots = ["altair (==5.0.1)", "ipython (==8.14.0)", "ipywidgets (==8.0.6)", "jupyterlab-geojson (==3.4.0)", "jupyterlab-language-pack-zh-cn (==4.0.post0)", "matplotlib (==3.7.1)", "nbconvert (>=7.0.0)", "pandas (==2.0.2)", "scipy (==1.10.1)", "vega-datasets (==0.9.0)"] test = ["coverage", "pytest (>=7.0)", "pytest-check-links (>=0.7)", "pytest-console-scripts", "pytest-cov", "pytest-jupyter (>=0.5.3)", "pytest-timeout", "pytest-tornasync", "requests", "requests-cache", "virtualenv"] @@ -1587,38 +1589,38 @@ olefile = ">=0.46" [[package]] name = "mypy" -version = "1.7.1" +version = "1.8.0" description = "Optional static typing for Python" optional = false python-versions = ">=3.8" files = [ - {file = "mypy-1.7.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:12cce78e329838d70a204293e7b29af9faa3ab14899aec397798a4b41be7f340"}, - {file = "mypy-1.7.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:1484b8fa2c10adf4474f016e09d7a159602f3239075c7bf9f1627f5acf40ad49"}, - {file = "mypy-1.7.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:31902408f4bf54108bbfb2e35369877c01c95adc6192958684473658c322c8a5"}, - {file = "mypy-1.7.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:f2c2521a8e4d6d769e3234350ba7b65ff5d527137cdcde13ff4d99114b0c8e7d"}, - {file = "mypy-1.7.1-cp310-cp310-win_amd64.whl", hash = "sha256:fcd2572dd4519e8a6642b733cd3a8cfc1ef94bafd0c1ceed9c94fe736cb65b6a"}, - {file = "mypy-1.7.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4b901927f16224d0d143b925ce9a4e6b3a758010673eeded9b748f250cf4e8f7"}, - {file = "mypy-1.7.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2f7f6985d05a4e3ce8255396df363046c28bea790e40617654e91ed580ca7c51"}, - {file = "mypy-1.7.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:944bdc21ebd620eafefc090cdf83158393ec2b1391578359776c00de00e8907a"}, - {file = "mypy-1.7.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:9c7ac372232c928fff0645d85f273a726970c014749b924ce5710d7d89763a28"}, - {file = "mypy-1.7.1-cp311-cp311-win_amd64.whl", hash = "sha256:f6efc9bd72258f89a3816e3a98c09d36f079c223aa345c659622f056b760ab42"}, - {file = "mypy-1.7.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:6dbdec441c60699288adf051f51a5d512b0d818526d1dcfff5a41f8cd8b4aaf1"}, - {file = "mypy-1.7.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4fc3d14ee80cd22367caaaf6e014494415bf440980a3045bf5045b525680ac33"}, - {file = "mypy-1.7.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2c6e4464ed5f01dc44dc9821caf67b60a4e5c3b04278286a85c067010653a0eb"}, - {file = "mypy-1.7.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:d9b338c19fa2412f76e17525c1b4f2c687a55b156320acb588df79f2e6fa9fea"}, - {file = "mypy-1.7.1-cp312-cp312-win_amd64.whl", hash = "sha256:204e0d6de5fd2317394a4eff62065614c4892d5a4d1a7ee55b765d7a3d9e3f82"}, - {file = "mypy-1.7.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:84860e06ba363d9c0eeabd45ac0fde4b903ad7aa4f93cd8b648385a888e23200"}, - {file = "mypy-1.7.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:8c5091ebd294f7628eb25ea554852a52058ac81472c921150e3a61cdd68f75a7"}, - {file = "mypy-1.7.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:40716d1f821b89838589e5b3106ebbc23636ffdef5abc31f7cd0266db936067e"}, - {file = "mypy-1.7.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:5cf3f0c5ac72139797953bd50bc6c95ac13075e62dbfcc923571180bebb662e9"}, - {file = "mypy-1.7.1-cp38-cp38-win_amd64.whl", hash = "sha256:78e25b2fd6cbb55ddfb8058417df193f0129cad5f4ee75d1502248e588d9e0d7"}, - {file = "mypy-1.7.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:75c4d2a6effd015786c87774e04331b6da863fc3fc4e8adfc3b40aa55ab516fe"}, - {file = "mypy-1.7.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:2643d145af5292ee956aa0a83c2ce1038a3bdb26e033dadeb2f7066fb0c9abce"}, - {file = "mypy-1.7.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75aa828610b67462ffe3057d4d8a4112105ed211596b750b53cbfe182f44777a"}, - {file = "mypy-1.7.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ee5d62d28b854eb61889cde4e1dbc10fbaa5560cb39780c3995f6737f7e82120"}, - {file = "mypy-1.7.1-cp39-cp39-win_amd64.whl", hash = "sha256:72cf32ce7dd3562373f78bd751f73c96cfb441de147cc2448a92c1a308bd0ca6"}, - {file = "mypy-1.7.1-py3-none-any.whl", hash = "sha256:f7c5d642db47376a0cc130f0de6d055056e010debdaf0707cd2b0fc7e7ef30ea"}, - {file = "mypy-1.7.1.tar.gz", hash = "sha256:fcb6d9afb1b6208b4c712af0dafdc650f518836065df0d4fb1d800f5d6773db2"}, + {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] @@ -1667,13 +1669,13 @@ test = ["flaky", "ipykernel (>=6.19.3)", "ipython", "ipywidgets", "nbconvert (>= [[package]] name = "nbconvert" -version = "7.12.0" +version = "7.14.0" description = "Converting Jupyter Notebooks" optional = false python-versions = ">=3.8" files = [ - {file = "nbconvert-7.12.0-py3-none-any.whl", hash = "sha256:5b6c848194d270cc55fb691169202620d7b52a12fec259508d142ecbe4219310"}, - {file = "nbconvert-7.12.0.tar.gz", hash = "sha256:b1564bd89f69a74cd6398b0362da94db07aafb991b7857216a766204a71612c0"}, + {file = "nbconvert-7.14.0-py3-none-any.whl", hash = "sha256:483dde47facdaa4875903d651305ad53cd76e2255ae3c61efe412a95f2d22a24"}, + {file = "nbconvert-7.14.0.tar.gz", hash = "sha256:92b9a44b63e5a7fb4f6fa0ef41261e35c16925046ccd1c04a5c8099bf100476e"}, ] [package.dependencies] @@ -1700,7 +1702,7 @@ docs = ["ipykernel", "ipython", "myst-parser", "nbsphinx (>=0.2.12)", "pydata-sp qtpdf = ["nbconvert[qtpng]"] qtpng = ["pyqtwebengine (>=5.15)"] serve = ["tornado (>=6.1)"] -test = ["flaky", "ipykernel", "ipywidgets (>=7)", "pytest"] +test = ["flaky", "ipykernel", "ipywidgets (>=7.5)", "pytest"] webpdf = ["playwright"] [[package]] @@ -1878,70 +1880,88 @@ files = [ [[package]] name = "pillow" -version = "10.1.0" +version = "10.2.0" description = "Python Imaging Library (Fork)" optional = true python-versions = ">=3.8" files = [ - {file = "Pillow-10.1.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:1ab05f3db77e98f93964697c8efc49c7954b08dd61cff526b7f2531a22410106"}, - {file = "Pillow-10.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6932a7652464746fcb484f7fc3618e6503d2066d853f68a4bd97193a3996e273"}, - {file = "Pillow-10.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a5f63b5a68daedc54c7c3464508d8c12075e56dcfbd42f8c1bf40169061ae666"}, - {file = "Pillow-10.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0949b55eb607898e28eaccb525ab104b2d86542a85c74baf3a6dc24002edec2"}, - {file = "Pillow-10.1.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:ae88931f93214777c7a3aa0a8f92a683f83ecde27f65a45f95f22d289a69e593"}, - {file = "Pillow-10.1.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:b0eb01ca85b2361b09480784a7931fc648ed8b7836f01fb9241141b968feb1db"}, - {file = "Pillow-10.1.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:d27b5997bdd2eb9fb199982bb7eb6164db0426904020dc38c10203187ae2ff2f"}, - {file = "Pillow-10.1.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:7df5608bc38bd37ef585ae9c38c9cd46d7c81498f086915b0f97255ea60c2818"}, - {file = "Pillow-10.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:41f67248d92a5e0a2076d3517d8d4b1e41a97e2df10eb8f93106c89107f38b57"}, - {file = "Pillow-10.1.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:1fb29c07478e6c06a46b867e43b0bcdb241b44cc52be9bc25ce5944eed4648e7"}, - {file = "Pillow-10.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2cdc65a46e74514ce742c2013cd4a2d12e8553e3a2563c64879f7c7e4d28bce7"}, - {file = "Pillow-10.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:50d08cd0a2ecd2a8657bd3d82c71efd5a58edb04d9308185d66c3a5a5bed9610"}, - {file = "Pillow-10.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:062a1610e3bc258bff2328ec43f34244fcec972ee0717200cb1425214fe5b839"}, - {file = "Pillow-10.1.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:61f1a9d247317fa08a308daaa8ee7b3f760ab1809ca2da14ecc88ae4257d6172"}, - {file = "Pillow-10.1.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:a646e48de237d860c36e0db37ecaecaa3619e6f3e9d5319e527ccbc8151df061"}, - {file = "Pillow-10.1.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:47e5bf85b80abc03be7455c95b6d6e4896a62f6541c1f2ce77a7d2bb832af262"}, - {file = "Pillow-10.1.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:a92386125e9ee90381c3369f57a2a50fa9e6aa8b1cf1d9c4b200d41a7dd8e992"}, - {file = "Pillow-10.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:0f7c276c05a9767e877a0b4c5050c8bee6a6d960d7f0c11ebda6b99746068c2a"}, - {file = "Pillow-10.1.0-cp312-cp312-macosx_10_10_x86_64.whl", hash = "sha256:a89b8312d51715b510a4fe9fc13686283f376cfd5abca8cd1c65e4c76e21081b"}, - {file = "Pillow-10.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:00f438bb841382b15d7deb9a05cc946ee0f2c352653c7aa659e75e592f6fa17d"}, - {file = "Pillow-10.1.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3d929a19f5469b3f4df33a3df2983db070ebb2088a1e145e18facbc28cae5b27"}, - {file = "Pillow-10.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9a92109192b360634a4489c0c756364c0c3a2992906752165ecb50544c251312"}, - {file = "Pillow-10.1.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:0248f86b3ea061e67817c47ecbe82c23f9dd5d5226200eb9090b3873d3ca32de"}, - {file = "Pillow-10.1.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:9882a7451c680c12f232a422730f986a1fcd808da0fd428f08b671237237d651"}, - {file = "Pillow-10.1.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:1c3ac5423c8c1da5928aa12c6e258921956757d976405e9467c5f39d1d577a4b"}, - {file = "Pillow-10.1.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:806abdd8249ba3953c33742506fe414880bad78ac25cc9a9b1c6ae97bedd573f"}, - {file = "Pillow-10.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:eaed6977fa73408b7b8a24e8b14e59e1668cfc0f4c40193ea7ced8e210adf996"}, - {file = "Pillow-10.1.0-cp38-cp38-macosx_10_10_x86_64.whl", hash = "sha256:fe1e26e1ffc38be097f0ba1d0d07fcade2bcfd1d023cda5b29935ae8052bd793"}, - {file = "Pillow-10.1.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7a7e3daa202beb61821c06d2517428e8e7c1aab08943e92ec9e5755c2fc9ba5e"}, - {file = "Pillow-10.1.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:24fadc71218ad2b8ffe437b54876c9382b4a29e030a05a9879f615091f42ffc2"}, - {file = "Pillow-10.1.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fa1d323703cfdac2036af05191b969b910d8f115cf53093125e4058f62012c9a"}, - {file = "Pillow-10.1.0-cp38-cp38-manylinux_2_28_aarch64.whl", hash = "sha256:912e3812a1dbbc834da2b32299b124b5ddcb664ed354916fd1ed6f193f0e2d01"}, - {file = "Pillow-10.1.0-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:7dbaa3c7de82ef37e7708521be41db5565004258ca76945ad74a8e998c30af8d"}, - {file = "Pillow-10.1.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:9d7bc666bd8c5a4225e7ac71f2f9d12466ec555e89092728ea0f5c0c2422ea80"}, - {file = "Pillow-10.1.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:baada14941c83079bf84c037e2d8b7506ce201e92e3d2fa0d1303507a8538212"}, - {file = "Pillow-10.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:2ef6721c97894a7aa77723740a09547197533146fba8355e86d6d9a4a1056b14"}, - {file = "Pillow-10.1.0-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:0a026c188be3b443916179f5d04548092e253beb0c3e2ee0a4e2cdad72f66099"}, - {file = "Pillow-10.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:04f6f6149f266a100374ca3cc368b67fb27c4af9f1cc8cb6306d849dcdf12616"}, - {file = "Pillow-10.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bb40c011447712d2e19cc261c82655f75f32cb724788df315ed992a4d65696bb"}, - {file = "Pillow-10.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1a8413794b4ad9719346cd9306118450b7b00d9a15846451549314a58ac42219"}, - {file = "Pillow-10.1.0-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:c9aeea7b63edb7884b031a35305629a7593272b54f429a9869a4f63a1bf04c34"}, - {file = "Pillow-10.1.0-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:b4005fee46ed9be0b8fb42be0c20e79411533d1fd58edabebc0dd24626882cfd"}, - {file = "Pillow-10.1.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:4d0152565c6aa6ebbfb1e5d8624140a440f2b99bf7afaafbdbf6430426497f28"}, - {file = "Pillow-10.1.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:d921bc90b1defa55c9917ca6b6b71430e4286fc9e44c55ead78ca1a9f9eba5f2"}, - {file = "Pillow-10.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:cfe96560c6ce2f4c07d6647af2d0f3c54cc33289894ebd88cfbb3bcd5391e256"}, - {file = "Pillow-10.1.0-pp310-pypy310_pp73-macosx_10_10_x86_64.whl", hash = "sha256:937bdc5a7f5343d1c97dc98149a0be7eb9704e937fe3dc7140e229ae4fc572a7"}, - {file = "Pillow-10.1.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b1c25762197144e211efb5f4e8ad656f36c8d214d390585d1d21281f46d556ba"}, - {file = "Pillow-10.1.0-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:afc8eef765d948543a4775f00b7b8c079b3321d6b675dde0d02afa2ee23000b4"}, - {file = "Pillow-10.1.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:883f216eac8712b83a63f41b76ddfb7b2afab1b74abbb413c5df6680f071a6b9"}, - {file = "Pillow-10.1.0-pp39-pypy39_pp73-macosx_10_10_x86_64.whl", hash = "sha256:b920e4d028f6442bea9a75b7491c063f0b9a3972520731ed26c83e254302eb1e"}, - {file = "Pillow-10.1.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1c41d960babf951e01a49c9746f92c5a7e0d939d1652d7ba30f6b3090f27e412"}, - {file = "Pillow-10.1.0-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:1fafabe50a6977ac70dfe829b2d5735fd54e190ab55259ec8aea4aaea412fa0b"}, - {file = "Pillow-10.1.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:3b834f4b16173e5b92ab6566f0473bfb09f939ba14b23b8da1f54fa63e4b623f"}, - {file = "Pillow-10.1.0.tar.gz", hash = "sha256:e6bf8de6c36ed96c86ea3b6e1d5273c53f46ef518a062464cd7ef5dd2cf92e38"}, + {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 = "pkgutil-resolve-name" @@ -2014,27 +2034,27 @@ wcwidth = "*" [[package]] name = "psutil" -version = "5.9.6" +version = "5.9.7" description = "Cross-platform lib for process and system monitoring in Python." optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" files = [ - {file = "psutil-5.9.6-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:fb8a697f11b0f5994550555fcfe3e69799e5b060c8ecf9e2f75c69302cc35c0d"}, - {file = "psutil-5.9.6-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:91ecd2d9c00db9817a4b4192107cf6954addb5d9d67a969a4f436dbc9200f88c"}, - {file = "psutil-5.9.6-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:10e8c17b4f898d64b121149afb136c53ea8b68c7531155147867b7b1ac9e7e28"}, - {file = "psutil-5.9.6-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:18cd22c5db486f33998f37e2bb054cc62fd06646995285e02a51b1e08da97017"}, - {file = "psutil-5.9.6-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:ca2780f5e038379e520281e4c032dddd086906ddff9ef0d1b9dcf00710e5071c"}, - {file = "psutil-5.9.6-cp27-none-win32.whl", hash = "sha256:70cb3beb98bc3fd5ac9ac617a327af7e7f826373ee64c80efd4eb2856e5051e9"}, - {file = "psutil-5.9.6-cp27-none-win_amd64.whl", hash = "sha256:51dc3d54607c73148f63732c727856f5febec1c7c336f8f41fcbd6315cce76ac"}, - {file = "psutil-5.9.6-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:c69596f9fc2f8acd574a12d5f8b7b1ba3765a641ea5d60fb4736bf3c08a8214a"}, - {file = "psutil-5.9.6-cp36-abi3-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:92e0cc43c524834af53e9d3369245e6cc3b130e78e26100d1f63cdb0abeb3d3c"}, - {file = "psutil-5.9.6-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:748c9dd2583ed86347ed65d0035f45fa8c851e8d90354c122ab72319b5f366f4"}, - {file = "psutil-5.9.6-cp36-cp36m-win32.whl", hash = "sha256:3ebf2158c16cc69db777e3c7decb3c0f43a7af94a60d72e87b2823aebac3d602"}, - {file = "psutil-5.9.6-cp36-cp36m-win_amd64.whl", hash = "sha256:ff18b8d1a784b810df0b0fff3bcb50ab941c3b8e2c8de5726f9c71c601c611aa"}, - {file = "psutil-5.9.6-cp37-abi3-win32.whl", hash = "sha256:a6f01f03bf1843280f4ad16f4bde26b817847b4c1a0db59bf6419807bc5ce05c"}, - {file = "psutil-5.9.6-cp37-abi3-win_amd64.whl", hash = "sha256:6e5fb8dc711a514da83098bc5234264e551ad980cec5f85dabf4d38ed6f15e9a"}, - {file = "psutil-5.9.6-cp38-abi3-macosx_11_0_arm64.whl", hash = "sha256:daecbcbd29b289aac14ece28eca6a3e60aa361754cf6da3dfb20d4d32b6c7f57"}, - {file = "psutil-5.9.6.tar.gz", hash = "sha256:e4b92ddcd7dd4cdd3f900180ea1e104932c7bce234fb88976e2a3b296441225a"}, + {file = "psutil-5.9.7-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:0bd41bf2d1463dfa535942b2a8f0e958acf6607ac0be52265ab31f7923bcd5e6"}, + {file = "psutil-5.9.7-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:5794944462509e49d4d458f4dbfb92c47539e7d8d15c796f141f474010084056"}, + {file = "psutil-5.9.7-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:fe361f743cb3389b8efda21980d93eb55c1f1e3898269bc9a2a1d0bb7b1f6508"}, + {file = "psutil-5.9.7-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:e469990e28f1ad738f65a42dcfc17adaed9d0f325d55047593cb9033a0ab63df"}, + {file = "psutil-5.9.7-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:3c4747a3e2ead1589e647e64aad601981f01b68f9398ddf94d01e3dc0d1e57c7"}, + {file = "psutil-5.9.7-cp27-none-win32.whl", hash = "sha256:1d4bc4a0148fdd7fd8f38e0498639ae128e64538faa507df25a20f8f7fb2341c"}, + {file = "psutil-5.9.7-cp27-none-win_amd64.whl", hash = "sha256:4c03362e280d06bbbfcd52f29acd79c733e0af33d707c54255d21029b8b32ba6"}, + {file = "psutil-5.9.7-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:ea36cc62e69a13ec52b2f625c27527f6e4479bca2b340b7a452af55b34fcbe2e"}, + {file = "psutil-5.9.7-cp36-abi3-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1132704b876e58d277168cd729d64750633d5ff0183acf5b3c986b8466cd0284"}, + {file = "psutil-5.9.7-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fe8b7f07948f1304497ce4f4684881250cd859b16d06a1dc4d7941eeb6233bfe"}, + {file = "psutil-5.9.7-cp36-cp36m-win32.whl", hash = "sha256:b27f8fdb190c8c03914f908a4555159327d7481dac2f01008d483137ef3311a9"}, + {file = "psutil-5.9.7-cp36-cp36m-win_amd64.whl", hash = "sha256:44969859757f4d8f2a9bd5b76eba8c3099a2c8cf3992ff62144061e39ba8568e"}, + {file = "psutil-5.9.7-cp37-abi3-win32.whl", hash = "sha256:c727ca5a9b2dd5193b8644b9f0c883d54f1248310023b5ad3e92036c5e2ada68"}, + {file = "psutil-5.9.7-cp37-abi3-win_amd64.whl", hash = "sha256:f37f87e4d73b79e6c5e749440c3113b81d1ee7d26f21c19c47371ddea834f414"}, + {file = "psutil-5.9.7-cp38-abi3-macosx_11_0_arm64.whl", hash = "sha256:032f4f2c909818c86cea4fe2cc407f1c0f0cde8e6c6d702b28b8ce0c0d143340"}, + {file = "psutil-5.9.7.tar.gz", hash = "sha256:3f02134e82cfb5d089fddf20bb2e03fd5cd52395321d1c8458a9e58500ff417c"}, ] [package.extras] @@ -2152,13 +2172,13 @@ files = [ [[package]] name = "pytest" -version = "7.4.3" +version = "7.4.4" description = "pytest: simple powerful testing with Python" optional = false python-versions = ">=3.7" files = [ - {file = "pytest-7.4.3-py3-none-any.whl", hash = "sha256:0d009c083ea859a71b76adf7c1d502e4bc170b80a8ef002da5806527b9591fac"}, - {file = "pytest-7.4.3.tar.gz", hash = "sha256:d989d136982de4e3b29dabcc838ad581c64e8ed52c11fbe86ddebd9da0818cd5"}, + {file = "pytest-7.4.4-py3-none-any.whl", hash = "sha256:b090cdf5ed60bf4c45261be03239c2c1c22df034fbffe691abe93cd80cea01d8"}, + {file = "pytest-7.4.4.tar.gz", hash = "sha256:2cf0005922c6ace4a3e2ec8b4080eb0d9753fdc93107415332f50ce9e7994280"}, ] [package.dependencies] @@ -2557,110 +2577,110 @@ files = [ [[package]] name = "rpds-py" -version = "0.13.2" +version = "0.16.2" description = "Python bindings to Rust's persistent data structures (rpds)" optional = false python-versions = ">=3.8" files = [ - {file = "rpds_py-0.13.2-cp310-cp310-macosx_10_7_x86_64.whl", hash = "sha256:1ceebd0ae4f3e9b2b6b553b51971921853ae4eebf3f54086be0565d59291e53d"}, - {file = "rpds_py-0.13.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:46e1ed994a0920f350a4547a38471217eb86f57377e9314fbaaa329b71b7dfe3"}, - {file = "rpds_py-0.13.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ee353bb51f648924926ed05e0122b6a0b1ae709396a80eb583449d5d477fcdf7"}, - {file = "rpds_py-0.13.2-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:530190eb0cd778363bbb7596612ded0bb9fef662daa98e9d92a0419ab27ae914"}, - {file = "rpds_py-0.13.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:29d311e44dd16d2434d5506d57ef4d7036544fc3c25c14b6992ef41f541b10fb"}, - {file = "rpds_py-0.13.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2e72f750048b32d39e87fc85c225c50b2a6715034848dbb196bf3348aa761fa1"}, - {file = "rpds_py-0.13.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:db09b98c7540df69d4b47218da3fbd7cb466db0fb932e971c321f1c76f155266"}, - {file = "rpds_py-0.13.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2ac26f50736324beb0282c819668328d53fc38543fa61eeea2c32ea8ea6eab8d"}, - {file = "rpds_py-0.13.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:12ecf89bd54734c3c2c79898ae2021dca42750c7bcfb67f8fb3315453738ac8f"}, - {file = "rpds_py-0.13.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:3a44c8440183b43167fd1a0819e8356692bf5db1ad14ce140dbd40a1485f2dea"}, - {file = "rpds_py-0.13.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:bcef4f2d3dc603150421de85c916da19471f24d838c3c62a4f04c1eb511642c1"}, - {file = "rpds_py-0.13.2-cp310-none-win32.whl", hash = "sha256:ee6faebb265e28920a6f23a7d4c362414b3f4bb30607141d718b991669e49ddc"}, - {file = "rpds_py-0.13.2-cp310-none-win_amd64.whl", hash = "sha256:ac96d67b37f28e4b6ecf507c3405f52a40658c0a806dffde624a8fcb0314d5fd"}, - {file = "rpds_py-0.13.2-cp311-cp311-macosx_10_7_x86_64.whl", hash = "sha256:b5f6328e8e2ae8238fc767703ab7b95785521c42bb2b8790984e3477d7fa71ad"}, - {file = "rpds_py-0.13.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:729408136ef8d45a28ee9a7411917c9e3459cf266c7e23c2f7d4bb8ef9e0da42"}, - {file = "rpds_py-0.13.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:65cfed9c807c27dee76407e8bb29e6f4e391e436774bcc769a037ff25ad8646e"}, - {file = "rpds_py-0.13.2-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:aefbdc934115d2f9278f153952003ac52cd2650e7313750390b334518c589568"}, - {file = "rpds_py-0.13.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d48db29bd47814671afdd76c7652aefacc25cf96aad6daefa82d738ee87461e2"}, - {file = "rpds_py-0.13.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3c55d7f2d817183d43220738270efd3ce4e7a7b7cbdaefa6d551ed3d6ed89190"}, - {file = "rpds_py-0.13.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6aadae3042f8e6db3376d9e91f194c606c9a45273c170621d46128f35aef7cd0"}, - {file = "rpds_py-0.13.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5feae2f9aa7270e2c071f488fab256d768e88e01b958f123a690f1cc3061a09c"}, - {file = "rpds_py-0.13.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:51967a67ea0d7b9b5cd86036878e2d82c0b6183616961c26d825b8c994d4f2c8"}, - {file = "rpds_py-0.13.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:4d0c10d803549427f427085ed7aebc39832f6e818a011dcd8785e9c6a1ba9b3e"}, - {file = "rpds_py-0.13.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:603d5868f7419081d616dab7ac3cfa285296735e7350f7b1e4f548f6f953ee7d"}, - {file = "rpds_py-0.13.2-cp311-none-win32.whl", hash = "sha256:b8996ffb60c69f677245f5abdbcc623e9442bcc91ed81b6cd6187129ad1fa3e7"}, - {file = "rpds_py-0.13.2-cp311-none-win_amd64.whl", hash = "sha256:5379e49d7e80dca9811b36894493d1c1ecb4c57de05c36f5d0dd09982af20211"}, - {file = "rpds_py-0.13.2-cp312-cp312-macosx_10_7_x86_64.whl", hash = "sha256:8a776a29b77fe0cc28fedfd87277b0d0f7aa930174b7e504d764e0b43a05f381"}, - {file = "rpds_py-0.13.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2a1472956c5bcc49fb0252b965239bffe801acc9394f8b7c1014ae9258e4572b"}, - {file = "rpds_py-0.13.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f252dfb4852a527987a9156cbcae3022a30f86c9d26f4f17b8c967d7580d65d2"}, - {file = "rpds_py-0.13.2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f0d320e70b6b2300ff6029e234e79fe44e9dbbfc7b98597ba28e054bd6606a57"}, - {file = "rpds_py-0.13.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ade2ccb937060c299ab0dfb2dea3d2ddf7e098ed63ee3d651ebfc2c8d1e8632a"}, - {file = "rpds_py-0.13.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b9d121be0217787a7d59a5c6195b0842d3f701007333426e5154bf72346aa658"}, - {file = "rpds_py-0.13.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8fa6bd071ec6d90f6e7baa66ae25820d57a8ab1b0a3c6d3edf1834d4b26fafa2"}, - {file = "rpds_py-0.13.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c918621ee0a3d1fe61c313f2489464f2ae3d13633e60f520a8002a5e910982ee"}, - {file = "rpds_py-0.13.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:25b28b3d33ec0a78e944aaaed7e5e2a94ac811bcd68b557ca48a0c30f87497d2"}, - {file = "rpds_py-0.13.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:31e220a040b89a01505128c2f8a59ee74732f666439a03e65ccbf3824cdddae7"}, - {file = "rpds_py-0.13.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:15253fff410873ebf3cfba1cc686a37711efcd9b8cb30ea21bb14a973e393f60"}, - {file = "rpds_py-0.13.2-cp312-none-win32.whl", hash = "sha256:b981a370f8f41c4024c170b42fbe9e691ae2dbc19d1d99151a69e2c84a0d194d"}, - {file = "rpds_py-0.13.2-cp312-none-win_amd64.whl", hash = "sha256:4c4e314d36d4f31236a545696a480aa04ea170a0b021e9a59ab1ed94d4c3ef27"}, - {file = "rpds_py-0.13.2-cp38-cp38-macosx_10_7_x86_64.whl", hash = "sha256:80e5acb81cb49fd9f2d5c08f8b74ffff14ee73b10ca88297ab4619e946bcb1e1"}, - {file = "rpds_py-0.13.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:efe093acc43e869348f6f2224df7f452eab63a2c60a6c6cd6b50fd35c4e075ba"}, - {file = "rpds_py-0.13.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8c2a61c0e4811012b0ba9f6cdcb4437865df5d29eab5d6018ba13cee1c3064a0"}, - {file = "rpds_py-0.13.2-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:751758d9dd04d548ec679224cc00e3591f5ebf1ff159ed0d4aba6a0746352452"}, - {file = "rpds_py-0.13.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6ba8858933f0c1a979781272a5f65646fca8c18c93c99c6ddb5513ad96fa54b1"}, - {file = "rpds_py-0.13.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bfdfbe6a36bc3059fff845d64c42f2644cf875c65f5005db54f90cdfdf1df815"}, - {file = "rpds_py-0.13.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aa0379c1935c44053c98826bc99ac95f3a5355675a297ac9ce0dfad0ce2d50ca"}, - {file = "rpds_py-0.13.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d5593855b5b2b73dd8413c3fdfa5d95b99d657658f947ba2c4318591e745d083"}, - {file = "rpds_py-0.13.2-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:2a7bef6977043673750a88da064fd513f89505111014b4e00fbdd13329cd4e9a"}, - {file = "rpds_py-0.13.2-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:3ab96754d23372009638a402a1ed12a27711598dd49d8316a22597141962fe66"}, - {file = "rpds_py-0.13.2-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:e06cfea0ece444571d24c18ed465bc93afb8c8d8d74422eb7026662f3d3f779b"}, - {file = "rpds_py-0.13.2-cp38-none-win32.whl", hash = "sha256:5493569f861fb7b05af6d048d00d773c6162415ae521b7010197c98810a14cab"}, - {file = "rpds_py-0.13.2-cp38-none-win_amd64.whl", hash = "sha256:b07501b720cf060c5856f7b5626e75b8e353b5f98b9b354a21eb4bfa47e421b1"}, - {file = "rpds_py-0.13.2-cp39-cp39-macosx_10_7_x86_64.whl", hash = "sha256:881df98f0a8404d32b6de0fd33e91c1b90ed1516a80d4d6dc69d414b8850474c"}, - {file = "rpds_py-0.13.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:d79c159adea0f1f4617f54aa156568ac69968f9ef4d1e5fefffc0a180830308e"}, - {file = "rpds_py-0.13.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:38d4f822ee2f338febcc85aaa2547eb5ba31ba6ff68d10b8ec988929d23bb6b4"}, - {file = "rpds_py-0.13.2-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5d75d6d220d55cdced2f32cc22f599475dbe881229aeddba6c79c2e9df35a2b3"}, - {file = "rpds_py-0.13.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5d97e9ae94fb96df1ee3cb09ca376c34e8a122f36927230f4c8a97f469994bff"}, - {file = "rpds_py-0.13.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:67a429520e97621a763cf9b3ba27574779c4e96e49a27ff8a1aa99ee70beb28a"}, - {file = "rpds_py-0.13.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:188435794405c7f0573311747c85a96b63c954a5f2111b1df8018979eca0f2f0"}, - {file = "rpds_py-0.13.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:38f9bf2ad754b4a45b8210a6c732fe876b8a14e14d5992a8c4b7c1ef78740f53"}, - {file = "rpds_py-0.13.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:a6ba2cb7d676e9415b9e9ac7e2aae401dc1b1e666943d1f7bc66223d3d73467b"}, - {file = "rpds_py-0.13.2-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:eaffbd8814bb1b5dc3ea156a4c5928081ba50419f9175f4fc95269e040eff8f0"}, - {file = "rpds_py-0.13.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:5a4c1058cdae6237d97af272b326e5f78ee7ee3bbffa6b24b09db4d828810468"}, - {file = "rpds_py-0.13.2-cp39-none-win32.whl", hash = "sha256:b5267feb19070bef34b8dea27e2b504ebd9d31748e3ecacb3a4101da6fcb255c"}, - {file = "rpds_py-0.13.2-cp39-none-win_amd64.whl", hash = "sha256:ddf23960cb42b69bce13045d5bc66f18c7d53774c66c13f24cf1b9c144ba3141"}, - {file = "rpds_py-0.13.2-pp310-pypy310_pp73-macosx_10_7_x86_64.whl", hash = "sha256:97163a1ab265a1073a6372eca9f4eeb9f8c6327457a0b22ddfc4a17dcd613e74"}, - {file = "rpds_py-0.13.2-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:25ea41635d22b2eb6326f58e608550e55d01df51b8a580ea7e75396bafbb28e9"}, - {file = "rpds_py-0.13.2-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76d59d4d451ba77f08cb4cd9268dec07be5bc65f73666302dbb5061989b17198"}, - {file = "rpds_py-0.13.2-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e7c564c58cf8f248fe859a4f0fe501b050663f3d7fbc342172f259124fb59933"}, - {file = "rpds_py-0.13.2-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:61dbc1e01dc0c5875da2f7ae36d6e918dc1b8d2ce04e871793976594aad8a57a"}, - {file = "rpds_py-0.13.2-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fdb82eb60d31b0c033a8e8ee9f3fc7dfbaa042211131c29da29aea8531b4f18f"}, - {file = "rpds_py-0.13.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d204957169f0b3511fb95395a9da7d4490fb361763a9f8b32b345a7fe119cb45"}, - {file = "rpds_py-0.13.2-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c45008ca79bad237cbc03c72bc5205e8c6f66403773929b1b50f7d84ef9e4d07"}, - {file = "rpds_py-0.13.2-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:79bf58c08f0756adba691d480b5a20e4ad23f33e1ae121584cf3a21717c36dfa"}, - {file = "rpds_py-0.13.2-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:e86593bf8637659e6a6ed58854b6c87ec4e9e45ee8a4adfd936831cef55c2d21"}, - {file = "rpds_py-0.13.2-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:d329896c40d9e1e5c7715c98529e4a188a1f2df51212fd65102b32465612b5dc"}, - {file = "rpds_py-0.13.2-pp38-pypy38_pp73-macosx_10_7_x86_64.whl", hash = "sha256:4a5375c5fff13f209527cd886dc75394f040c7d1ecad0a2cb0627f13ebe78a12"}, - {file = "rpds_py-0.13.2-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:06d218e4464d31301e943b65b2c6919318ea6f69703a351961e1baaf60347276"}, - {file = "rpds_py-0.13.2-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c1f41d32a2ddc5a94df4b829b395916a4b7f103350fa76ba6de625fcb9e773ac"}, - {file = "rpds_py-0.13.2-pp38-pypy38_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6bc568b05e02cd612be53900c88aaa55012e744930ba2eeb56279db4c6676eb3"}, - {file = "rpds_py-0.13.2-pp38-pypy38_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9d94d78418203904730585efa71002286ac4c8ac0689d0eb61e3c465f9e608ff"}, - {file = "rpds_py-0.13.2-pp38-pypy38_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bed0252c85e21cf73d2d033643c945b460d6a02fc4a7d644e3b2d6f5f2956c64"}, - {file = "rpds_py-0.13.2-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:244e173bb6d8f3b2f0c4d7370a1aa341f35da3e57ffd1798e5b2917b91731fd3"}, - {file = "rpds_py-0.13.2-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:7f55cd9cf1564b7b03f238e4c017ca4794c05b01a783e9291065cb2858d86ce4"}, - {file = "rpds_py-0.13.2-pp38-pypy38_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:f03a1b3a4c03e3e0161642ac5367f08479ab29972ea0ffcd4fa18f729cd2be0a"}, - {file = "rpds_py-0.13.2-pp38-pypy38_pp73-musllinux_1_2_i686.whl", hash = "sha256:f5f4424cb87a20b016bfdc157ff48757b89d2cc426256961643d443c6c277007"}, - {file = "rpds_py-0.13.2-pp38-pypy38_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:c82bbf7e03748417c3a88c1b0b291288ce3e4887a795a3addaa7a1cfd9e7153e"}, - {file = "rpds_py-0.13.2-pp39-pypy39_pp73-macosx_10_7_x86_64.whl", hash = "sha256:c0095b8aa3e432e32d372e9a7737e65b58d5ed23b9620fea7cb81f17672f1fa1"}, - {file = "rpds_py-0.13.2-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:4c2d26aa03d877c9730bf005621c92da263523a1e99247590abbbe252ccb7824"}, - {file = "rpds_py-0.13.2-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:96f2975fb14f39c5fe75203f33dd3010fe37d1c4e33177feef1107b5ced750e3"}, - {file = "rpds_py-0.13.2-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:4dcc5ee1d0275cb78d443fdebd0241e58772a354a6d518b1d7af1580bbd2c4e8"}, - {file = "rpds_py-0.13.2-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:61d42d2b08430854485135504f672c14d4fc644dd243a9c17e7c4e0faf5ed07e"}, - {file = "rpds_py-0.13.2-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d3a61e928feddc458a55110f42f626a2a20bea942ccedb6fb4cee70b4830ed41"}, - {file = "rpds_py-0.13.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7de12b69d95072394998c622cfd7e8cea8f560db5fca6a62a148f902a1029f8b"}, - {file = "rpds_py-0.13.2-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:87a90f5545fd61f6964e65eebde4dc3fa8660bb7d87adb01d4cf17e0a2b484ad"}, - {file = "rpds_py-0.13.2-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:9c95a1a290f9acf7a8f2ebbdd183e99215d491beea52d61aa2a7a7d2c618ddc6"}, - {file = "rpds_py-0.13.2-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:35f53c76a712e323c779ca39b9a81b13f219a8e3bc15f106ed1e1462d56fcfe9"}, - {file = "rpds_py-0.13.2-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:96fb0899bb2ab353f42e5374c8f0789f54e0a94ef2f02b9ac7149c56622eaf31"}, - {file = "rpds_py-0.13.2.tar.gz", hash = "sha256:f8eae66a1304de7368932b42d801c67969fd090ddb1a7a24f27b435ed4bed68f"}, + {file = "rpds_py-0.16.2-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:509b617ac787cd1149600e731db9274ebbef094503ca25158e6f23edaba1ca8f"}, + {file = "rpds_py-0.16.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:413b9c17388bbd0d87a329d8e30c1a4c6e44e2bb25457f43725a8e6fe4161e9e"}, + {file = "rpds_py-0.16.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2946b120718eba9af2b4dd103affc1164a87b9e9ebff8c3e4c05d7b7a7e274e2"}, + {file = "rpds_py-0.16.2-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:35ae5ece284cf36464eb160880018cf6088a9ac5ddc72292a6092b6ef3f4da53"}, + {file = "rpds_py-0.16.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3dc6a7620ba7639a3db6213da61312cb4aa9ac0ca6e00dc1cbbdc21c2aa6eb57"}, + {file = "rpds_py-0.16.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8cb6fe8ecdfffa0e711a75c931fb39f4ba382b4b3ccedeca43f18693864fe850"}, + {file = "rpds_py-0.16.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6dace7b26a13353e24613417ce2239491b40a6ad44e5776a18eaff7733488b44"}, + {file = "rpds_py-0.16.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1bdbc5fcb04a7309074de6b67fa9bc4b418ab3fc435fec1f2779a0eced688d04"}, + {file = "rpds_py-0.16.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:f42e25c016927e2a6b1ce748112c3ab134261fc2ddc867e92d02006103e1b1b7"}, + {file = "rpds_py-0.16.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:eab36eae3f3e8e24b05748ec9acc66286662f5d25c52ad70cadab544e034536b"}, + {file = "rpds_py-0.16.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:0474df4ade9a3b4af96c3d36eb81856cb9462e4c6657d4caecfd840d2a13f3c9"}, + {file = "rpds_py-0.16.2-cp310-none-win32.whl", hash = "sha256:84c5a4d1f9dd7e2d2c44097fb09fffe728629bad31eb56caf97719e55575aa82"}, + {file = "rpds_py-0.16.2-cp310-none-win_amd64.whl", hash = "sha256:2bd82db36cd70b3628c0c57d81d2438e8dd4b7b32a6a9f25f24ab0e657cb6c4e"}, + {file = "rpds_py-0.16.2-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:adc0c3d6fc6ae35fee3e4917628983f6ce630d513cbaad575b4517d47e81b4bb"}, + {file = "rpds_py-0.16.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ec23fcad480e77ede06cf4127a25fc440f7489922e17fc058f426b5256ee0edb"}, + {file = "rpds_py-0.16.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:07aab64e2808c3ebac2a44f67e9dc0543812b715126dfd6fe4264df527556cb6"}, + {file = "rpds_py-0.16.2-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a4ebb8b20bd09c5ce7884c8f0388801100f5e75e7f733b1b6613c713371feefc"}, + {file = "rpds_py-0.16.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a3d7e2ea25d3517c6d7e5a1cc3702cffa6bd18d9ef8d08d9af6717fc1c700eed"}, + {file = "rpds_py-0.16.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f28ac0e8e7242d140f99402a903a2c596ab71550272ae9247ad78f9a932b5698"}, + {file = "rpds_py-0.16.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:19f00f57fdd38db4bb5ad09f9ead1b535332dbf624200e9029a45f1f35527ebb"}, + {file = "rpds_py-0.16.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:3da5a4c56953bdbf6d04447c3410309616c54433146ccdb4a277b9cb499bc10e"}, + {file = "rpds_py-0.16.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:ec2e1cf025b2c0f48ec17ff3e642661da7ee332d326f2e6619366ce8e221f018"}, + {file = "rpds_py-0.16.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:e0441fb4fdd39a230477b2ca9be90868af64425bfe7b122b57e61e45737a653b"}, + {file = "rpds_py-0.16.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:9f0350ef2fba5f34eb0c9000ea328e51b9572b403d2f7f3b19f24085f6f598e8"}, + {file = "rpds_py-0.16.2-cp311-none-win32.whl", hash = "sha256:5a80e2f83391ad0808b4646732af2a7b67550b98f0cae056cb3b40622a83dbb3"}, + {file = "rpds_py-0.16.2-cp311-none-win_amd64.whl", hash = "sha256:e04e56b4ca7a770593633556e8e9e46579d66ec2ada846b401252a2bdcf70a6d"}, + {file = "rpds_py-0.16.2-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:5e6caa3809e50690bd92fa490f5c38caa86082c8c3315aa438bce43786d5e90d"}, + {file = "rpds_py-0.16.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2e53b9b25cac9065328901713a7e9e3b12e4f57ef4280b370fbbf6fef2052eef"}, + {file = "rpds_py-0.16.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:af27423662f32d7501a00c5e7342f7dbd1e4a718aea7a239781357d15d437133"}, + {file = "rpds_py-0.16.2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:43d4dd5fb16eb3825742bad8339d454054261ab59fed2fbac84e1d84d5aae7ba"}, + {file = "rpds_py-0.16.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e061de3b745fe611e23cd7318aec2c8b0e4153939c25c9202a5811ca911fd733"}, + {file = "rpds_py-0.16.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3b811d182ad17ea294f2ec63c0621e7be92a1141e1012383461872cead87468f"}, + {file = "rpds_py-0.16.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5552f328eaef1a75ff129d4d0c437bf44e43f9436d3996e8eab623ea0f5fcf73"}, + {file = "rpds_py-0.16.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:dcbe1f8dd179e4d69b70b1f1d9bb6fd1e7e1bdc9c9aad345cdeb332e29d40748"}, + {file = "rpds_py-0.16.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8aad80645a011abae487d356e0ceb359f4938dfb6f7bcc410027ed7ae4f7bb8b"}, + {file = "rpds_py-0.16.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:b6f5549d6ed1da9bfe3631ca9483ae906f21410be2445b73443fa9f017601c6f"}, + {file = "rpds_py-0.16.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:d452817e0d9c749c431a1121d56a777bd7099b720b3d1c820f1725cb40928f58"}, + {file = "rpds_py-0.16.2-cp312-none-win32.whl", hash = "sha256:888a97002e986eca10d8546e3c8b97da1d47ad8b69726dcfeb3e56348ebb28a3"}, + {file = "rpds_py-0.16.2-cp312-none-win_amd64.whl", hash = "sha256:d8dda2a806dfa4a9b795950c4f5cc56d6d6159f7d68080aedaff3bdc9b5032f5"}, + {file = "rpds_py-0.16.2-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:071980663c273bf3d388fe5c794c547e6f35ba3335477072c713a3176bf14a60"}, + {file = "rpds_py-0.16.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:726ac36e8a3bb8daef2fd482534cabc5e17334052447008405daca7ca04a3108"}, + {file = "rpds_py-0.16.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e9e557db6a177470316c82f023e5d571811c9a4422b5ea084c85da9aa3c035fc"}, + {file = "rpds_py-0.16.2-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:90123853fc8b1747f80b0d354be3d122b4365a93e50fc3aacc9fb4c2488845d6"}, + {file = "rpds_py-0.16.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a61f659665a39a4d17d699ab3593d7116d66e1e2e3f03ef3fb8f484e91908808"}, + {file = "rpds_py-0.16.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cc97f0640e91d7776530f06e6836c546c1c752a52de158720c4224c9e8053cad"}, + {file = "rpds_py-0.16.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:44a54e99a2b9693a37ebf245937fd6e9228b4cbd64b9cc961e1f3391ec6c7391"}, + {file = "rpds_py-0.16.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:bd4b677d929cf1f6bac07ad76e0f2d5de367e6373351c01a9c0a39f6b21b4a8b"}, + {file = "rpds_py-0.16.2-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:5ef00873303d678aaf8b0627e111fd434925ca01c657dbb2641410f1cdaef261"}, + {file = "rpds_py-0.16.2-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:349cb40897fd529ca15317c22c0eab67f5ac5178b5bd2c6adc86172045210acc"}, + {file = "rpds_py-0.16.2-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:2ddef620e70eaffebed5932ce754d539c0930f676aae6212f8e16cd9743dd365"}, + {file = "rpds_py-0.16.2-cp38-none-win32.whl", hash = "sha256:882ce6e25e585949c3d9f9abd29202367175e0aab3aba0c58c9abbb37d4982ff"}, + {file = "rpds_py-0.16.2-cp38-none-win_amd64.whl", hash = "sha256:f4bd4578e44f26997e9e56c96dedc5f1af43cc9d16c4daa29c771a00b2a26851"}, + {file = "rpds_py-0.16.2-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:69ac7ea9897ec201ce68b48582f3eb34a3f9924488a5432a93f177bf76a82a7e"}, + {file = "rpds_py-0.16.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a9880b4656efe36ccad41edc66789e191e5ee19a1ea8811e0aed6f69851a82f4"}, + {file = "rpds_py-0.16.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ee94cb58c0ba2c62ee108c2b7c9131b2c66a29e82746e8fa3aa1a1effbd3dcf1"}, + {file = "rpds_py-0.16.2-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:24f7a2eb3866a9e91f4599851e0c8d39878a470044875c49bd528d2b9b88361c"}, + {file = "rpds_py-0.16.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ca57468da2d9a660bcf8961637c85f2fbb2aa64d9bc3f9484e30c3f9f67b1dd7"}, + {file = "rpds_py-0.16.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ccd4e400309e1f34a5095bf9249d371f0fd60f8a3a5c4a791cad7b99ce1fd38d"}, + {file = "rpds_py-0.16.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80443fe2f7b3ea3934c5d75fb0e04a5dbb4a8e943e5ff2de0dec059202b70a8b"}, + {file = "rpds_py-0.16.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4d6a9f052e72d493efd92a77f861e45bab2f6be63e37fa8ecf0c6fd1a58fedb0"}, + {file = "rpds_py-0.16.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:35953f4f2b3216421af86fd236b7c0c65935936a94ea83ddbd4904ba60757773"}, + {file = "rpds_py-0.16.2-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:981d135c7cdaf6cd8eadae1c950de43b976de8f09d8e800feed307140d3d6d00"}, + {file = "rpds_py-0.16.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:d0dd7ed2f16df2e129496e7fbe59a34bc2d7fc8db443a606644d069eb69cbd45"}, + {file = "rpds_py-0.16.2-cp39-none-win32.whl", hash = "sha256:703d95c75a72e902544fda08e965885525e297578317989fd15a6ce58414b41d"}, + {file = "rpds_py-0.16.2-cp39-none-win_amd64.whl", hash = "sha256:e93ec1b300acf89730cf27975ef574396bc04edecc358e9bd116fb387a123239"}, + {file = "rpds_py-0.16.2-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:44627b6ca7308680a70766454db5249105fa6344853af6762eaad4158a2feebe"}, + {file = "rpds_py-0.16.2-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:3f91df8e6dbb7360e176d1affd5fb0246d2b88d16aa5ebc7db94fd66b68b61da"}, + {file = "rpds_py-0.16.2-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6d904c5693e08bad240f16d79305edba78276be87061c872a4a15e2c301fa2c0"}, + {file = "rpds_py-0.16.2-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:290a81cfbe4673285cdf140ec5cd1658ffbf63ab359f2b352ebe172e7cfa5bf0"}, + {file = "rpds_py-0.16.2-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b634c5ec0103c5cbebc24ebac4872b045cccb9456fc59efdcf6fe39775365bd2"}, + {file = "rpds_py-0.16.2-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a297a4d08cc67c7466c873c78039d87840fb50d05473db0ec1b7b03d179bf322"}, + {file = "rpds_py-0.16.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b2e75e17bd0bb66ee34a707da677e47c14ee51ccef78ed6a263a4cc965a072a1"}, + {file = "rpds_py-0.16.2-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f1b9d9260e06ea017feb7172976ab261e011c1dc2f8883c7c274f6b2aabfe01a"}, + {file = "rpds_py-0.16.2-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:162d7cd9cd311c1b0ff1c55a024b8f38bd8aad1876b648821da08adc40e95734"}, + {file = "rpds_py-0.16.2-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:9b32f742ce5b57201305f19c2ef7a184b52f6f9ba6871cc042c2a61f0d6b49b8"}, + {file = "rpds_py-0.16.2-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:ac08472f41ea77cd6a5dae36ae7d4ed3951d6602833af87532b556c1b4601d63"}, + {file = "rpds_py-0.16.2-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:495a14b72bbe217f2695dcd9b5ab14d4f8066a00f5d209ed94f0aca307f85f6e"}, + {file = "rpds_py-0.16.2-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:8d6b6937ae9eac6d6c0ca3c42774d89fa311f55adff3970fb364b34abde6ed3d"}, + {file = "rpds_py-0.16.2-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6a61226465bda9283686db8f17d02569a98e4b13c637be5a26d44aa1f1e361c2"}, + {file = "rpds_py-0.16.2-pp38-pypy38_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5cf6af100ffb5c195beec11ffaa8cf8523057f123afa2944e6571d54da84cdc9"}, + {file = "rpds_py-0.16.2-pp38-pypy38_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6df15846ee3fb2e6397fe25d7ca6624af9f89587f3f259d177b556fed6bebe2c"}, + {file = "rpds_py-0.16.2-pp38-pypy38_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1be2f033df1b8be8c3167ba3c29d5dca425592ee31e35eac52050623afba5772"}, + {file = "rpds_py-0.16.2-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:96f957d6ab25a78b9e7fc9749d754b98eac825a112b4e666525ce89afcbd9ed5"}, + {file = "rpds_py-0.16.2-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:088396c7c70e59872f67462fcac3ecbded5233385797021976a09ebd55961dfe"}, + {file = "rpds_py-0.16.2-pp38-pypy38_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:4c46ad6356e1561f2a54f08367d1d2e70a0a1bb2db2282d2c1972c1d38eafc3b"}, + {file = "rpds_py-0.16.2-pp38-pypy38_pp73-musllinux_1_2_i686.whl", hash = "sha256:47713dc4fce213f5c74ca8a1f6a59b622fc1b90868deb8e8e4d993e421b4b39d"}, + {file = "rpds_py-0.16.2-pp38-pypy38_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:f811771019f063bbd0aa7bb72c8a934bc13ebacb4672d712fc1639cfd314cccc"}, + {file = "rpds_py-0.16.2-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:f19afcfc0dd0dca35694df441e9b0f95bc231b512f51bded3c3d8ca32153ec19"}, + {file = "rpds_py-0.16.2-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:a4b682c5775d6a3d21e314c10124599976809455ee67020e8e72df1769b87bc3"}, + {file = "rpds_py-0.16.2-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c647ca87fc0ebe808a41de912e9a1bfef9acb85257e5d63691364ac16b81c1f0"}, + {file = "rpds_py-0.16.2-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:302bd4983bbd47063e452c38be66153760112f6d3635c7eeefc094299fa400a9"}, + {file = "rpds_py-0.16.2-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bf721ede3eb7b829e4a9b8142bd55db0bdc82902720548a703f7e601ee13bdc3"}, + {file = "rpds_py-0.16.2-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:358dafc89ce3894c7f486c615ba914609f38277ef67f566abc4c854d23b997fa"}, + {file = "rpds_py-0.16.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cad0f59ee3dc35526039f4bc23642d52d5f6616b5f687d846bfc6d0d6d486db0"}, + {file = "rpds_py-0.16.2-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:cffa76b385dfe1e38527662a302b19ffb0e7f5cf7dd5e89186d2c94a22dd9d0c"}, + {file = "rpds_py-0.16.2-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:83640a5d7cd3bff694747d50436b8b541b5b9b9782b0c8c1688931d6ee1a1f2d"}, + {file = "rpds_py-0.16.2-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:ed99b4f7179d2111702020fd7d156e88acd533f5a7d3971353e568b6051d5c97"}, + {file = "rpds_py-0.16.2-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:4022b9dc620e14f30201a8a73898a873c8e910cb642bcd2f3411123bc527f6ac"}, + {file = "rpds_py-0.16.2.tar.gz", hash = "sha256:781ef8bfc091b19960fc0142a23aedadafa826bc32b433fdfe6fd7f964d7ef44"}, ] [[package]] @@ -3101,13 +3121,13 @@ files = [ [[package]] name = "traitlets" -version = "5.14.0" +version = "5.14.1" description = "Traitlets Python configuration system" optional = false python-versions = ">=3.8" files = [ - {file = "traitlets-5.14.0-py3-none-any.whl", hash = "sha256:f14949d23829023013c47df20b4a76ccd1a85effb786dc060f34de7948361b33"}, - {file = "traitlets-5.14.0.tar.gz", hash = "sha256:fcdaa8ac49c04dfa0ed3ee3384ef6dfdb5d6f3741502be247279407679296772"}, + {file = "traitlets-5.14.1-py3-none-any.whl", hash = "sha256:2e5a030e6eff91737c643231bfcf04a65b0132078dad75e4936700b213652e74"}, + {file = "traitlets-5.14.1.tar.gz", hash = "sha256:8585105b371a04b8316a43d5ce29c098575c2e477850b62b848b964f1444527e"}, ] [package.extras] @@ -3208,13 +3228,13 @@ types-pyOpenSSL = "*" [[package]] name = "types-requests" -version = "2.31.0.10" +version = "2.31.0.20231231" description = "Typing stubs for requests" optional = false python-versions = ">=3.7" files = [ - {file = "types-requests-2.31.0.10.tar.gz", hash = "sha256:dc5852a76f1eaf60eafa81a2e50aefa3d1f015c34cf0cba130930866b1b22a92"}, - {file = "types_requests-2.31.0.10-py3-none-any.whl", hash = "sha256:b32b9a86beffa876c0c3ac99a4cd3b8b51e973fb8e3bd4e0a6bb32c7efad80fc"}, + {file = "types-requests-2.31.0.20231231.tar.gz", hash = "sha256:0f8c0c9764773384122813548d9eea92a5c4e1f33ed54556b508968ec5065cee"}, + {file = "types_requests-2.31.0.20231231-py3-none-any.whl", hash = "sha256:2e2230c7bc8dd63fa3153c1c0ae335f8a368447f0582fc332f17d54f88e69027"}, ] [package.dependencies] @@ -3244,13 +3264,13 @@ files = [ [[package]] name = "tzdata" -version = "2023.3" +version = "2023.4" description = "Provider of IANA time zone data" optional = true python-versions = ">=2" files = [ - {file = "tzdata-2023.3-py2.py3-none-any.whl", hash = "sha256:7e65763eef3120314099b6939b5546db7adce1e7d6f2e179e3df563c70511eda"}, - {file = "tzdata-2023.3.tar.gz", hash = "sha256:11ef1e08e54acb0d4f95bdb1be05da659673de4acbd21bf9c69e94cc5e907a3a"}, + {file = "tzdata-2023.4-py2.py3-none-any.whl", hash = "sha256:aa3ace4329eeacda5b7beb7ea08ece826c28d761cda36e747cfbf97996d39bf3"}, + {file = "tzdata-2023.4.tar.gz", hash = "sha256:dd54c94f294765522c77399649b4fefd95522479a664a0cec87f41bebc6148c9"}, ] [[package]] @@ -3497,4 +3517,4 @@ virustotal = ["validators"] [metadata] lock-version = "2.0" python-versions = "^3.8" -content-hash = "d424bb1bb0e2d19be80879d794f7b560d373c675071e09ab4c9dee33ba684b0f" +content-hash = "85a1cc6f45b693da2ec5c9a7b1a72085c3a2da96a7e358623b3eeb41ea89e339" diff --git a/pymisp/mispevent.py b/pymisp/mispevent.py index ef83a2f..0575851 100644 --- a/pymisp/mispevent.py +++ b/pymisp/mispevent.py @@ -15,6 +15,7 @@ import logging import hashlib from pathlib import Path from typing import List, Optional, Union, IO, Dict, Any +import warnings from .abstract import AbstractMISP, MISPTag from .exceptions import (UnknownMISPObjectTemplate, InvalidMISPGalaxy, InvalidMISPObject, @@ -29,11 +30,6 @@ try: except ImportError: logger.exception("Cannot import dateutil") -try: - import jsonschema # type: ignore -except ImportError: - logger.exception("Cannot import jsonschema") - try: # pyme renamed to gpg the 2016-10-28 import gpg # type: ignore @@ -1764,8 +1760,7 @@ class MISPEvent(AbstractMISP): event.pop('Object', None) self.from_dict(**event) if validate: - json_schema = self._load_json(self.resources_path / self.__schema_file) - jsonschema.validate({"Event": self.jsonable()}, json_schema) + warnings.warn('''The validate parameter is deprecated because PyMISP is more flexible at loading event than the schema''') def __setattr__(self, name, value): if name in ['date']: diff --git a/pyproject.toml b/pyproject.toml index e804cb7..b5283e0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -43,7 +43,6 @@ include = [ python = "^3.8" requests = "^2.31.0" python-dateutil = "^2.8.2" -jsonschema = "^4.20.0" deprecated = "^1.2.14" extract_msg = {version = "^0.47.0", optional = true} RTFDE = {version = "^0.1.1", optional = true} @@ -76,13 +75,13 @@ brotli = ['urllib3'] [tool.poetry.group.dev.dependencies] requests-mock = "^1.11.0" -mypy = "^1.7.1" +mypy = "^1.8.0" ipython = [ {version = "<8.13.0", python = "<3.9"}, {version = "^8.13.0", python = ">=3.9"} ] -jupyterlab = "^4.0.9" -types-requests = "^2.31.0.10" +jupyterlab = "^4.0.10" +types-requests = "^2.31.0.20231231" types-python-dateutil = "^2.8.19.14" types-redis = "^4.6.0.11" types-Flask = "^1.1.6" From 81f5d596a7dd5cb1ca7213ac4fbdf07b402420b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Vinot?= Date: Thu, 4 Jan 2024 13:38:59 +0100 Subject: [PATCH 22/80] chg: Bump version --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index b5283e0..48dbc86 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "pymisp" -version = "2.4.182" +version = "2.4.183" description = "Python API for MISP." authors = ["Raphaël Vinot "] license = "BSD-2-Clause" From b77493abd1c4bc02756f8220217bc6b0867b385a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Vinot?= Date: Thu, 4 Jan 2024 13:42:56 +0100 Subject: [PATCH 23/80] chg: Bump objects --- pymisp/data/misp-objects | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pymisp/data/misp-objects b/pymisp/data/misp-objects index 587b298..888e0dc 160000 --- a/pymisp/data/misp-objects +++ b/pymisp/data/misp-objects @@ -1 +1 @@ -Subproject commit 587b298e1e7f87426182d55d44aa045a1522dc98 +Subproject commit 888e0dceda905076635ecc7d589ee3effe3c45d6 From dd628a7fe10699ce9efdf2bc9fa7d6d1c1dc484a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Vinot?= Date: Thu, 4 Jan 2024 14:10:04 +0100 Subject: [PATCH 24/80] chg: Bump changelog --- CHANGELOG.txt | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 5bf234e..f12dcc5 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -2,6 +2,28 @@ Changelog ========= +v2.4.183 (2024-01-04) +--------------------- + +New +~~~ +- Documentation to install PyMISP on offline machine. [Raphaël Vinot] + +Changes +~~~~~~~ +- Bump objects. [Raphaël Vinot] +- Bump version. [Raphaël Vinot] +- Remove jsonschema from dependencies. [Raphaël Vinot] +- Encrypt malicious js. [Raphaël Vinot] + +Other +~~~~~ +- Fix api ssl verify typing. [Steven] +- Add HTTPS Adapter. [Steven] + + Add the ability to provide a custom HTTPS adapter to the PyMISP class. With M2Crypto and m2requests, this can enable mutual TLS with hardware tokens. + + v2.4.182 (2023-12-14) --------------------- From fca0b233cd0ddaced0cef9104cfd8d07fe82720f Mon Sep 17 00:00:00 2001 From: Jakub Onderka Date: Fri, 5 Jan 2024 21:18:44 +0100 Subject: [PATCH 25/80] new: [internal] Add support for orjson orjson is much faster library for decoding and encoding JSON formats --- .github/workflows/pytest.yml | 6 +++ pymisp/abstract.py | 81 ++++++++++++++++-------------------- pymisp/api.py | 24 ++++++----- pymisp/mispevent.py | 13 +++--- 4 files changed, 64 insertions(+), 60 deletions(-) diff --git a/.github/workflows/pytest.yml b/.github/workflows/pytest.yml index 08ff3e7..febc048 100644 --- a/.github/workflows/pytest.yml +++ b/.github/workflows/pytest.yml @@ -36,5 +36,11 @@ jobs: poetry run pytest --cov=pymisp tests/test_*.py poetry run mypy tests/testlive_comprehensive.py tests/test_mispevent.py tests/testlive_sync.py pymisp + - name: Test with nosetests with orjson + run: | + pip3 install orjson + poetry run pytest --cov=pymisp tests/test_*.py + poetry run mypy tests/testlive_comprehensive.py tests/test_mispevent.py tests/testlive_sync.py pymisp + - name: Upload coverage to Codecov uses: codecov/codecov-action@v3 diff --git a/pymisp/abstract.py b/pymisp/abstract.py index 15a123c..8a4be01 100644 --- a/pymisp/abstract.py +++ b/pymisp/abstract.py @@ -1,41 +1,33 @@ #!/usr/bin/env python3 -# -*- coding: utf-8 -*- - +import logging from datetime import date, datetime - from deprecated import deprecated # type: ignore from json import JSONEncoder from uuid import UUID from abc import ABCMeta - -try: - from rapidjson import load # type: ignore - from rapidjson import loads # type: ignore - from rapidjson import dumps # type: ignore - HAS_RAPIDJSON = True -except ImportError: - from json import load - from json import loads - from json import dumps - HAS_RAPIDJSON = False - -import logging from enum import Enum from typing import Union, Optional, Any, Dict, List, Set, Mapping - -from .exceptions import PyMISPInvalidFormat, PyMISPError - - from collections.abc import MutableMapping from functools import lru_cache from pathlib import Path +try: + import orjson # type: ignore + from orjson import loads, dumps # type: ignore + HAS_ORJSON = True +except ImportError: + from json import loads, dumps + HAS_ORJSON = False + +from .exceptions import PyMISPInvalidFormat, PyMISPError + logger = logging.getLogger('pymisp') + resources_path = Path(__file__).parent / 'data' misp_objects_path = resources_path / 'misp-objects' / 'objects' -with (resources_path / 'describeTypes.json').open('r') as f: - describe_types = load(f)['result'] +with (resources_path / 'describeTypes.json').open('rb') as f: + describe_types = loads(f.read())['result'] class MISPFileCache(object): @@ -43,11 +35,11 @@ class MISPFileCache(object): @staticmethod @lru_cache(maxsize=150) - def _load_json(path: Path) -> Union[dict, None]: + def _load_json(path: Path) -> Optional[dict]: if not path.exists(): return None - with path.open('r', encoding='utf-8') as f: - data = load(f) + with path.open('rb') as f: + data = loads(f.read()) return data @@ -249,6 +241,15 @@ class AbstractMISP(MutableMapping, MISPFileCache, metaclass=ABCMeta): def to_json(self, sort_keys: bool = False, indent: Optional[int] = None) -> str: """Dump recursively any class of type MISPAbstract to a json string""" + if HAS_ORJSON: + option = 0 + if sort_keys: + option |= orjson.OPT_SORT_KEYS + if indent: + option |= orjson.OPT_INDENT_2 + + return dumps(self, default=pymisp_json_default, option=option).decode("utf-8") + return dumps(self, default=pymisp_json_default, sort_keys=sort_keys, indent=indent) def __getitem__(self, key): @@ -406,23 +407,13 @@ class MISPTag(AbstractMISP): return '<{self.__class__.__name__}(NotInitialized)>'.format(self=self) -if HAS_RAPIDJSON: - def pymisp_json_default(obj: Union[AbstractMISP, datetime, date, Enum, UUID]) -> Union[Dict, str]: - if isinstance(obj, AbstractMISP): - return obj.jsonable() - elif isinstance(obj, (datetime, date)): - return obj.isoformat() - elif isinstance(obj, Enum): - return obj.value - elif isinstance(obj, UUID): - return str(obj) -else: - def pymisp_json_default(obj: Union[AbstractMISP, datetime, date, Enum, UUID]) -> Union[Dict, str]: - if isinstance(obj, AbstractMISP): - return obj.jsonable() - elif isinstance(obj, (datetime, date)): - return obj.isoformat() - elif isinstance(obj, Enum): - return obj.value - elif isinstance(obj, UUID): - return str(obj) +# UUID, datetime, date and Enum is serialized by ORJSON by default +def pymisp_json_default(obj: Union[AbstractMISP, datetime, date, Enum, UUID]) -> Union[Dict, str]: + if isinstance(obj, AbstractMISP): + return obj.jsonable() + elif isinstance(obj, (datetime, date)): + return obj.isoformat() + elif isinstance(obj, Enum): + return obj.value + elif isinstance(obj, UUID): + return str(obj) diff --git a/pymisp/api.py b/pymisp/api.py index baceea7..85f6b00 100644 --- a/pymisp/api.py +++ b/pymisp/api.py @@ -1,13 +1,9 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- - from typing import TypeVar, Optional, Tuple, List, Dict, Union, Any, Mapping, Iterable, MutableMapping from datetime import date, datetime import csv from pathlib import Path import logging from urllib.parse import urljoin -import json import requests from requests.auth import AuthBase import re @@ -18,6 +14,14 @@ import copy import urllib3 # type: ignore from io import BytesIO, StringIO +try: + # orjson is optional dependency that speedups parsing and encoding JSON + from orjson import loads, dumps # type: ignore + HAS_ORJSON = True +except ImportError: + from json import loads, dumps + HAS_ORJSON = False + from . import __version__, everything_broken from .exceptions import MISPServerError, PyMISPUnexpectedResponse, PyMISPError, NoURL, NoKey from .mispevent import MISPEvent, MISPAttribute, MISPSighting, MISPLog, MISPObject, \ @@ -297,7 +301,7 @@ class PyMISP: """Get the most recent version from github""" r = requests.get('https://raw.githubusercontent.com/MISP/MISP/2.4/VERSION.json') if r.status_code == 200: - master_version = json.loads(r.text) + master_version = loads(r.content) return {'version': '{}.{}.{}'.format(master_version['major'], master_version['minor'], master_version['hotfix'])} return {'error': 'Impossible to retrieve the version of the master branch.'} @@ -3345,7 +3349,7 @@ class PyMISP: """ query: Dict[str, Any] = {'setting': user_setting} if isinstance(value, dict): - value = json.dumps(value) + value = dumps(value).decode("utf-8") if HAS_ORJSON else dumps(value) query['value'] = value if user: query['user_id'] = get_uuid_or_id_from_abstract_misp(user) @@ -3682,7 +3686,7 @@ class PyMISP: if 400 <= response.status_code < 500: # The server returns a json message with the error details try: - error_message = response.json() + error_message = loads(response.content) except Exception: raise MISPServerError(f'Error code {response.status_code}:\n{response.text}') @@ -3692,7 +3696,7 @@ class PyMISP: # At this point, we had no error. try: - response_json = response.json() + response_json = loads(response.content) logger.debug(response_json) if isinstance(response_json, dict) and response_json.get('response') is not None: # Cleanup. @@ -3721,7 +3725,7 @@ class PyMISP: if url[0] == '/': # strip it: it will fail if MISP is in a sub directory url = url[1:] - # Cake PHP being an idiot, it doesn't accepts %20 (space) in the URL path, + # Cake PHP being an idiot, it doesn't accept %20 (space) in the URL path, # so we need to make it a + instead and hope for the best url = url.replace(' ', '+') url = urljoin(self.root_url, url) @@ -3733,7 +3737,7 @@ class PyMISP: if isinstance(data, dict): # Remove None values. data = {k: v for k, v in data.items() if v is not None} - d = json.dumps(data, default=pymisp_json_default) + d = dumps(data, default=pymisp_json_default) logger.debug(f'{request_type} - {url}') if d is not None: diff --git a/pymisp/mispevent.py b/pymisp/mispevent.py index 0575851..f0e6949 100644 --- a/pymisp/mispevent.py +++ b/pymisp/mispevent.py @@ -1,8 +1,5 @@ -# -*- coding: utf-8 -*- - from datetime import timezone, datetime, date import copy -import json import os import base64 import sys @@ -17,6 +14,12 @@ from pathlib import Path from typing import List, Optional, Union, IO, Dict, Any import warnings +try: + # orjson is optional dependency that speedups parsing and encoding JSON + import orjson as json # type: ignore +except ImportError: + import json + from .abstract import AbstractMISP, MISPTag from .exceptions import (UnknownMISPObjectTemplate, InvalidMISPGalaxy, InvalidMISPObject, PyMISPError, NewEventError, NewAttributeError, NewEventReportError, @@ -1090,7 +1093,7 @@ class MISPObject(AbstractMISP): self._validate() return super(MISPObject, self).to_dict(json_format) - def to_json(self, sort_keys: bool = False, indent: Optional[int] = None, strict: bool = False): + def to_json(self, sort_keys: bool = False, indent: Optional[int] = None, strict: bool = False) -> str: if strict or self._strict and self._known_template: self._validate() return super(MISPObject, self).to_json(sort_keys=sort_keys, indent=indent) @@ -1760,7 +1763,7 @@ class MISPEvent(AbstractMISP): event.pop('Object', None) self.from_dict(**event) if validate: - warnings.warn('''The validate parameter is deprecated because PyMISP is more flexible at loading event than the schema''') + warnings.warn('The validate parameter is deprecated because PyMISP is more flexible at loading event than the schema') def __setattr__(self, name, value): if name in ['date']: From 8f747c0f9e74655af938feb3febc6e3199ee82cf Mon Sep 17 00:00:00 2001 From: Jakub Onderka Date: Fri, 5 Jan 2024 21:47:39 +0100 Subject: [PATCH 26/80] chg: [internal] Update poetry.lock --- poetry.lock | 35 +++++++++++++++++++++++++++++------ 1 file changed, 29 insertions(+), 6 deletions(-) diff --git a/poetry.lock b/poetry.lock index 7cf0ed1..f469575 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1183,6 +1183,7 @@ optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*, !=3.6.*" files = [ {file = "jsonpointer-2.4-py2.py3-none-any.whl", hash = "sha256:15d51bba20eea3165644553647711d150376234112651b4f1811022aecad7d7a"}, + {file = "jsonpointer-2.4.tar.gz", hash = "sha256:585cee82b70211fa9e6043b7bb89db6e1aa49524340dde8ad6b63206ea689d88"}, ] [[package]] @@ -1515,6 +1516,16 @@ files = [ {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:5bbe06f8eeafd38e5d0a4894ffec89378b6c6a625ff57e3028921f8ff59318ac"}, {file = "MarkupSafe-2.1.3-cp311-cp311-win32.whl", hash = "sha256:dd15ff04ffd7e05ffcb7fe79f1b98041b8ea30ae9234aed2a9168b5797c3effb"}, {file = "MarkupSafe-2.1.3-cp311-cp311-win_amd64.whl", hash = "sha256:134da1eca9ec0ae528110ccc9e48041e0828d79f24121a1a146161103c76e686"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:f698de3fd0c4e6972b92290a45bd9b1536bffe8c6759c62471efaa8acb4c37bc"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:aa57bd9cf8ae831a362185ee444e15a93ecb2e344c8e52e4d721ea3ab6ef1823"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ffcc3f7c66b5f5b7931a5aa68fc9cecc51e685ef90282f4a82f0f5e9b704ad11"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47d4f1c5f80fc62fdd7777d0d40a2e9dda0a05883ab11374334f6c4de38adffd"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1f67c7038d560d92149c060157d623c542173016c4babc0c1913cca0564b9939"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:9aad3c1755095ce347e26488214ef77e0485a3c34a50c5a5e2471dff60b9dd9c"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:14ff806850827afd6b07a5f32bd917fb7f45b046ba40c57abdb636674a8b559c"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8f9293864fe09b8149f0cc42ce56e3f0e54de883a9de90cd427f191c346eb2e1"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-win32.whl", hash = "sha256:715d3562f79d540f251b99ebd6d8baa547118974341db04f5ad06d5ea3eb8007"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-win_amd64.whl", hash = "sha256:1b8dd8c3fd14349433c79fa8abeb573a55fc0fdd769133baac1f5e07abf54aeb"}, {file = "MarkupSafe-2.1.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:8e254ae696c88d98da6555f5ace2279cf7cd5b3f52be2b5cf97feafe883b58d2"}, {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb0932dc158471523c9637e807d9bfb93e06a95cbf010f1a38b98623b929ef2b"}, {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9402b03f1a1b4dc4c19845e5c749e3ab82d5078d16a2a4c2cd2df62d57bb0707"}, @@ -1574,13 +1585,13 @@ files = [ [[package]] name = "msoffcrypto-tool" -version = "5.1.1" +version = "5.2.0" description = "Python tool and library for decrypting MS Office files with passwords or other keys" optional = true python-versions = ">=3.8,<4.0" files = [ - {file = "msoffcrypto_tool-5.1.1-py3-none-any.whl", hash = "sha256:27475aaf8a70485471ad86426c0be10ee4e24c6fad70335e4a8f88d2da323ca1"}, - {file = "msoffcrypto_tool-5.1.1.tar.gz", hash = "sha256:5585a303fa3ee49eec0253f912be17b82cf83f13f0f7489b4ea10f4ecb285278"}, + {file = "msoffcrypto_tool-5.2.0-py3-none-any.whl", hash = "sha256:2c6c1040df7a4f8e08256f9562f7898d49ec99ae7a6525f9725681b799b8af70"}, + {file = "msoffcrypto_tool-5.2.0.tar.gz", hash = "sha256:2f334cecd19eaa7426f26fc6f661a30268d4817e48d4c006708b4b29dcab6d7f"}, ] [package.dependencies] @@ -2122,6 +2133,8 @@ files = [ {file = "pydeep2-0.5.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2283893e25826b547dd1e5c71a010e86ddfd7270e2f2b8c90973c1d7984c7eb7"}, {file = "pydeep2-0.5.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f248e3161deb53d46a9368a7c164e36d83004faf2f11625d47a5cf23a6bdd2cb"}, {file = "pydeep2-0.5.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a13fca9be89a9fa8d92a4f49d7b9191eef94555f8ddf030fb2be4c8c15ad618c"}, + {file = "pydeep2-0.5.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d1cb4757db97ac15ddf034c21cd6bab984f841586b6d53984e63c9a7803b2cd4"}, + {file = "pydeep2-0.5.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7809a1d6640bdbee68f075d53229d05229e11b4711f232728dd540f68e6483a4"}, {file = "pydeep2-0.5.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0fedc1c9660cb5d0b73ad0b5f1dbffe16990e6721cbfc6454571a4b9882d0ea4"}, {file = "pydeep2-0.5.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7ca68f7d63e2ef510d410d20b223e8e97df41707fb50c4c526b6dd1d8698d9e6"}, {file = "pydeep2-0.5.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:199d05d8b4b7544509a2ba4802ead4b41dfe7859e0ecea9d9be9e41939f11660"}, @@ -2307,6 +2320,7 @@ files = [ {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"}, @@ -2314,8 +2328,15 @@ files = [ {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"}, @@ -2332,6 +2353,7 @@ files = [ {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"}, @@ -2339,6 +2361,7 @@ files = [ {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"}, @@ -2477,13 +2500,13 @@ files = [ [[package]] name = "referencing" -version = "0.32.0" +version = "0.32.1" description = "JSON Referencing + Python" optional = false python-versions = ">=3.8" files = [ - {file = "referencing-0.32.0-py3-none-any.whl", hash = "sha256:bdcd3efb936f82ff86f993093f6da7435c7de69a3b3a5a06678a6050184bee99"}, - {file = "referencing-0.32.0.tar.gz", hash = "sha256:689e64fe121843dcfd57b71933318ef1f91188ffb45367332700a86ac8fd6161"}, + {file = "referencing-0.32.1-py3-none-any.whl", hash = "sha256:7e4dc12271d8e15612bfe35792f5ea1c40970dadf8624602e33db2758f7ee554"}, + {file = "referencing-0.32.1.tar.gz", hash = "sha256:3c57da0513e9563eb7e203ebe9bb3a1b509b042016433bd1e45a2853466c3dd3"}, ] [package.dependencies] From 85ac94cc1cb616250140ee2c41931b41da44f267 Mon Sep 17 00:00:00 2001 From: Jakub Onderka Date: Sat, 6 Jan 2024 11:47:37 +0100 Subject: [PATCH 27/80] fix: [internal] README typos --- README.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 5c1509f..89da00f 100644 --- a/README.md +++ b/README.md @@ -125,7 +125,6 @@ logging.basicConfig(level=logging.DEBUG, filename="debug.log", filemode='w', for # From poetry pytest --cov=pymisp tests/test_*.py tests/testlive_comprehensive.py:TestComprehensive.[test_name] - ``` ## Documentation @@ -180,9 +179,9 @@ poetry build mv dist/*.whl offline/packages/ ``` -2. Copy the content of `offline/packages/` to the machine with no internet access. +3. Copy the content of `offline/packages/` to the machine with no internet access. -3. Install the packages: +4. Install the packages: ```bash python -m pip install --no-index --no-deps packages/*.whl From 1d24c1b3cee00ac887dba1a77be81aaaaceed2b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Vinot?= Date: Tue, 9 Jan 2024 12:40:09 +0100 Subject: [PATCH 28/80] chg: make the publish_timestamp a string, as per specs --- pymisp/mispevent.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pymisp/mispevent.py b/pymisp/mispevent.py index f0e6949..9c1c3ff 100644 --- a/pymisp/mispevent.py +++ b/pymisp/mispevent.py @@ -1883,9 +1883,9 @@ class MISPEvent(AbstractMISP): self.date = self.date.date() to_return['date'] = self.date.isoformat() if to_return.get('publish_timestamp'): - to_return['publish_timestamp'] = self._datetime_to_timestamp(self.publish_timestamp) + to_return['publish_timestamp'] = str(self._datetime_to_timestamp(self.publish_timestamp)) if to_return.get('sighting_timestamp'): - to_return['sighting_timestamp'] = self._datetime_to_timestamp(self.sighting_timestamp) + to_return['sighting_timestamp'] = str(self._datetime_to_timestamp(self.sighting_timestamp)) return to_return From fb8da4a28bea40a11e4acae6e52822b43ff768ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Vinot?= Date: Tue, 9 Jan 2024 13:07:38 +0100 Subject: [PATCH 29/80] fix: make publish_timestamp a string in tests --- tests/mispevent_testfiles/existing_event.json | 2 +- tests/mispevent_testfiles/existing_event_edited.json | 2 +- tests/mispevent_testfiles/malware_exist.json | 2 +- tests/mispevent_testfiles/shadow.json | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/mispevent_testfiles/existing_event.json b/tests/mispevent_testfiles/existing_event.json index 6d04a38..a123662 100644 --- a/tests/mispevent_testfiles/existing_event.json +++ b/tests/mispevent_testfiles/existing_event.json @@ -4590,7 +4590,7 @@ "org_id": "2", "orgc_id": "2", "proposal_email_lock": false, - "publish_timestamp": 0, + "publish_timestamp": "0", "published": false, "sharing_group_id": "0", "threat_level_id": "3", diff --git a/tests/mispevent_testfiles/existing_event_edited.json b/tests/mispevent_testfiles/existing_event_edited.json index b5937d3..da10762 100644 --- a/tests/mispevent_testfiles/existing_event_edited.json +++ b/tests/mispevent_testfiles/existing_event_edited.json @@ -4593,7 +4593,7 @@ "org_id": "2", "orgc_id": "2", "proposal_email_lock": false, - "publish_timestamp": 0, + "publish_timestamp": "0", "published": false, "sharing_group_id": "0", "threat_level_id": "3", diff --git a/tests/mispevent_testfiles/malware_exist.json b/tests/mispevent_testfiles/malware_exist.json index d118168..013304c 100644 --- a/tests/mispevent_testfiles/malware_exist.json +++ b/tests/mispevent_testfiles/malware_exist.json @@ -13,7 +13,7 @@ "distribution": "0", "proposal_email_lock": false, "locked": false, - "publish_timestamp": 0, + "publish_timestamp": "0", "sharing_group_id": "0", "disable_correlation": false, "event_creator_email": "raphael.vinot@circl.lu", diff --git a/tests/mispevent_testfiles/shadow.json b/tests/mispevent_testfiles/shadow.json index de0d5ad..61b484c 100644 --- a/tests/mispevent_testfiles/shadow.json +++ b/tests/mispevent_testfiles/shadow.json @@ -138,7 +138,7 @@ "org_id": "1", "orgc_id": "1", "proposal_email_lock": true, - "publish_timestamp": 0, + "publish_timestamp": "0", "published": false, "sharing_group_id": "0", "threat_level_id": "1", From a255ed417064b36afd74e3b14096dfaa9af4bf90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Vinot?= Date: Wed, 10 Jan 2024 11:42:29 +0100 Subject: [PATCH 30/80] chg: Bump deps, try to install with python 3.12 --- .github/workflows/pytest.yml | 2 +- poetry.lock | 134 +++++++++++++++++++++-------------- pyproject.toml | 11 +-- 3 files changed, 86 insertions(+), 61 deletions(-) diff --git a/.github/workflows/pytest.yml b/.github/workflows/pytest.yml index febc048..f61ef93 100644 --- a/.github/workflows/pytest.yml +++ b/.github/workflows/pytest.yml @@ -13,7 +13,7 @@ jobs: strategy: fail-fast: false matrix: - python-version: [3.8, 3.9, '3.10', '3.11'] + python-version: [3.8, 3.9, '3.10', '3.11', '3.12'] steps: diff --git a/poetry.lock b/poetry.lock index f469575..f6d1197 100644 --- a/poetry.lock +++ b/poetry.lock @@ -11,6 +11,17 @@ files = [ {file = "alabaster-0.7.13.tar.gz", hash = "sha256:a27a4a084d5e690e16e01e03ad2b2e552c61a65469419b907243193de1a84ae2"}, ] +[[package]] +name = "alabaster" +version = "0.7.16" +description = "A light, configurable Sphinx theme" +optional = true +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 = "anyio" version = "4.2.0" @@ -1111,6 +1122,42 @@ qtconsole = ["qtconsole"] test = ["pickleshare", "pytest (<7.1)", "pytest-asyncio (<0.22)", "testpath"] test-extra = ["curio", "matplotlib (!=3.2.0)", "nbformat", "numpy (>=1.22)", "pandas", "pickleshare", "pytest (<7.1)", "pytest-asyncio (<0.22)", "testpath", "trio"] +[[package]] +name = "ipython" +version = "8.20.0" +description = "IPython: Productive Interactive Computing" +optional = false +python-versions = ">=3.10" +files = [ + {file = "ipython-8.20.0-py3-none-any.whl", hash = "sha256:bc9716aad6f29f36c449e30821c9dd0c1c1a7b59ddcc26931685b87b4c569619"}, + {file = "ipython-8.20.0.tar.gz", hash = "sha256:2f21bd3fc1d51550c89ee3944ae04bbc7bc79e129ea0937da6e6c68bfdbf117a"}, +] + +[package.dependencies] +colorama = {version = "*", markers = "sys_platform == \"win32\""} +decorator = "*" +exceptiongroup = {version = "*", markers = "python_version < \"3.11\""} +jedi = ">=0.16" +matplotlib-inline = "*" +pexpect = {version = ">4.3", markers = "sys_platform != \"win32\""} +prompt-toolkit = ">=3.0.41,<3.1.0" +pygments = ">=2.4.0" +stack-data = "*" +traitlets = ">=5" + +[package.extras] +all = ["black", "curio", "docrepr", "exceptiongroup", "ipykernel", "ipyparallel", "ipywidgets", "matplotlib", "matplotlib (!=3.2.0)", "nbconvert", "nbformat", "notebook", "numpy (>=1.23)", "pandas", "pickleshare", "pytest", "pytest-asyncio (<0.22)", "qtconsole", "setuptools (>=18.5)", "sphinx (>=1.3)", "sphinx-rtd-theme", "stack-data", "testpath", "trio", "typing-extensions"] +black = ["black"] +doc = ["docrepr", "exceptiongroup", "ipykernel", "matplotlib", "pickleshare", "pytest", "pytest-asyncio (<0.22)", "setuptools (>=18.5)", "sphinx (>=1.3)", "sphinx-rtd-theme", "stack-data", "testpath", "typing-extensions"] +kernel = ["ipykernel"] +nbconvert = ["nbconvert"] +nbformat = ["nbformat"] +notebook = ["ipywidgets", "notebook"] +parallel = ["ipyparallel"] +qtconsole = ["qtconsole"] +test = ["pickleshare", "pytest", "pytest-asyncio (<0.22)", "testpath"] +test-extra = ["curio", "matplotlib (!=3.2.0)", "nbformat", "numpy (>=1.23)", "pandas", "pickleshare", "pytest", "pytest-asyncio (<0.22)", "testpath", "trio"] + [[package]] name = "isoduration" version = "20.11.0" @@ -1183,7 +1230,6 @@ optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*, !=3.6.*" files = [ {file = "jsonpointer-2.4-py2.py3-none-any.whl", hash = "sha256:15d51bba20eea3165644553647711d150376234112651b4f1811022aecad7d7a"}, - {file = "jsonpointer-2.4.tar.gz", hash = "sha256:585cee82b70211fa9e6043b7bb89db6e1aa49524340dde8ad6b63206ea689d88"}, ] [[package]] @@ -1257,13 +1303,13 @@ test = ["coverage", "ipykernel (>=6.14)", "mypy", "paramiko", "pre-commit", "pyt [[package]] name = "jupyter-core" -version = "5.7.0" +version = "5.7.1" description = "Jupyter core package. A base package on which Jupyter projects rely." optional = false python-versions = ">=3.8" files = [ - {file = "jupyter_core-5.7.0-py3-none-any.whl", hash = "sha256:16eea462f7dad23ba9f86542bdf17f830804e2028eb48d609b6134d91681e983"}, - {file = "jupyter_core-5.7.0.tar.gz", hash = "sha256:cb8d3ed92144d2463a3c5664fdd686a3f0c1442ea45df8babb1c1a9e6333fe03"}, + {file = "jupyter_core-5.7.1-py3-none-any.whl", hash = "sha256:c65c82126453a723a2804aa52409930434598fd9d35091d63dfb919d2b765bb7"}, + {file = "jupyter_core-5.7.1.tar.gz", hash = "sha256:de61a9d7fc71240f688b2fb5ab659fbb56979458dc66a71decd098e03c79e218"}, ] [package.dependencies] @@ -1317,13 +1363,13 @@ jupyter-server = ">=1.1.2" [[package]] name = "jupyter-server" -version = "2.12.2" +version = "2.12.3" description = "The backend—i.e. core services, APIs, and REST endpoints—to Jupyter web applications." optional = false python-versions = ">=3.8" files = [ - {file = "jupyter_server-2.12.2-py3-none-any.whl", hash = "sha256:abcfa33f98a959f908c8733aa2d9fa0101d26941cbd49b148f4cef4d3046fc61"}, - {file = "jupyter_server-2.12.2.tar.gz", hash = "sha256:5eae86be15224b5375cdec0c3542ce72ff20f7a25297a2a8166a250bb455a519"}, + {file = "jupyter_server-2.12.3-py3-none-any.whl", hash = "sha256:6f85310ea5e6068568a521f079fba99d8d17e4884dd1d602ab0f43b3115204a8"}, + {file = "jupyter_server-2.12.3.tar.gz", hash = "sha256:a1d2d51e497b1a6256c48b6940b0dd49b2553981baf1690077c37792f1fa23a1"}, ] [package.dependencies] @@ -1516,16 +1562,6 @@ files = [ {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:5bbe06f8eeafd38e5d0a4894ffec89378b6c6a625ff57e3028921f8ff59318ac"}, {file = "MarkupSafe-2.1.3-cp311-cp311-win32.whl", hash = "sha256:dd15ff04ffd7e05ffcb7fe79f1b98041b8ea30ae9234aed2a9168b5797c3effb"}, {file = "MarkupSafe-2.1.3-cp311-cp311-win_amd64.whl", hash = "sha256:134da1eca9ec0ae528110ccc9e48041e0828d79f24121a1a146161103c76e686"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:f698de3fd0c4e6972b92290a45bd9b1536bffe8c6759c62471efaa8acb4c37bc"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:aa57bd9cf8ae831a362185ee444e15a93ecb2e344c8e52e4d721ea3ab6ef1823"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ffcc3f7c66b5f5b7931a5aa68fc9cecc51e685ef90282f4a82f0f5e9b704ad11"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47d4f1c5f80fc62fdd7777d0d40a2e9dda0a05883ab11374334f6c4de38adffd"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1f67c7038d560d92149c060157d623c542173016c4babc0c1913cca0564b9939"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:9aad3c1755095ce347e26488214ef77e0485a3c34a50c5a5e2471dff60b9dd9c"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:14ff806850827afd6b07a5f32bd917fb7f45b046ba40c57abdb636674a8b559c"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8f9293864fe09b8149f0cc42ce56e3f0e54de883a9de90cd427f191c346eb2e1"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-win32.whl", hash = "sha256:715d3562f79d540f251b99ebd6d8baa547118974341db04f5ad06d5ea3eb8007"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-win_amd64.whl", hash = "sha256:1b8dd8c3fd14349433c79fa8abeb573a55fc0fdd769133baac1f5e07abf54aeb"}, {file = "MarkupSafe-2.1.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:8e254ae696c88d98da6555f5ace2279cf7cd5b3f52be2b5cf97feafe883b58d2"}, {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb0932dc158471523c9637e807d9bfb93e06a95cbf010f1a38b98623b929ef2b"}, {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9402b03f1a1b4dc4c19845e5c749e3ab82d5078d16a2a4c2cd2df62d57bb0707"}, @@ -2084,13 +2120,13 @@ files = [ [[package]] name = "publicsuffixlist" -version = "0.10.0.20231214" +version = "0.10.0.20240108" description = "publicsuffixlist implement" optional = true python-versions = ">=2.6" files = [ - {file = "publicsuffixlist-0.10.0.20231214-py2.py3-none-any.whl", hash = "sha256:10e227902e3b2acefb604b5de8a8a7d3df237f2885f06762d47fdbc9e0528b67"}, - {file = "publicsuffixlist-0.10.0.20231214.tar.gz", hash = "sha256:76a2ed46814f091ea867fb40a6c20c142a437af7aae7ac8eb425ddc464bcb8e1"}, + {file = "publicsuffixlist-0.10.0.20240108-py2.py3-none-any.whl", hash = "sha256:72ac774728036610501353789125a7adc57a793646cf6c6f1f7cc7458c913a8a"}, + {file = "publicsuffixlist-0.10.0.20240108.tar.gz", hash = "sha256:2d15301cbef4b5ecc9bfa47b38959af73350915748d44b2f91db2a8fc3b98d24"}, ] [package.extras] @@ -2133,8 +2169,6 @@ files = [ {file = "pydeep2-0.5.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2283893e25826b547dd1e5c71a010e86ddfd7270e2f2b8c90973c1d7984c7eb7"}, {file = "pydeep2-0.5.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f248e3161deb53d46a9368a7c164e36d83004faf2f11625d47a5cf23a6bdd2cb"}, {file = "pydeep2-0.5.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a13fca9be89a9fa8d92a4f49d7b9191eef94555f8ddf030fb2be4c8c15ad618c"}, - {file = "pydeep2-0.5.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d1cb4757db97ac15ddf034c21cd6bab984f841586b6d53984e63c9a7803b2cd4"}, - {file = "pydeep2-0.5.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7809a1d6640bdbee68f075d53229d05229e11b4711f232728dd540f68e6483a4"}, {file = "pydeep2-0.5.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0fedc1c9660cb5d0b73ad0b5f1dbffe16990e6721cbfc6454571a4b9882d0ea4"}, {file = "pydeep2-0.5.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7ca68f7d63e2ef510d410d20b223e8e97df41707fb50c4c526b6dd1d8698d9e6"}, {file = "pydeep2-0.5.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:199d05d8b4b7544509a2ba4802ead4b41dfe7859e0ecea9d9be9e41939f11660"}, @@ -2320,7 +2354,6 @@ files = [ {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"}, @@ -2328,15 +2361,8 @@ files = [ {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"}, @@ -2353,7 +2379,6 @@ files = [ {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"}, @@ -2361,7 +2386,6 @@ files = [ {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"}, @@ -2515,13 +2539,13 @@ rpds-py = ">=0.7.0" [[package]] name = "reportlab" -version = "4.0.8" +version = "4.0.9" description = "The Reportlab Toolkit" optional = true python-versions = ">=3.7,<4" files = [ - {file = "reportlab-4.0.8-py3-none-any.whl", hash = "sha256:d00693de8ab8761b122e409de883ba976c24839f93867090c0d40b5d5906e847"}, - {file = "reportlab-4.0.8.tar.gz", hash = "sha256:169945817a1a7759fb7b7dae528c2f8064fc21d16338d9b572ebdcb756740853"}, + {file = "reportlab-4.0.9-py3-none-any.whl", hash = "sha256:c9656216321897486e323be138f7aea67851cedc116b8cc35f8ec7f8cc763538"}, + {file = "reportlab-4.0.9.tar.gz", hash = "sha256:f32bff66a0fda234202e1e33eaf77f25008871a61cb01cd91584a521a04c0047"}, ] [package.dependencies] @@ -3211,13 +3235,13 @@ files = [ [[package]] name = "types-pyopenssl" -version = "23.3.0.0" +version = "23.3.0.20240106" description = "Typing stubs for pyOpenSSL" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "types-pyOpenSSL-23.3.0.0.tar.gz", hash = "sha256:5ffb077fe70b699c88d5caab999ae80e192fe28bf6cda7989b7e79b1e4e2dcd3"}, - {file = "types_pyOpenSSL-23.3.0.0-py3-none-any.whl", hash = "sha256:00171433653265843b7469ddb9f3c86d698668064cc33ef10537822156130ebf"}, + {file = "types-pyOpenSSL-23.3.0.20240106.tar.gz", hash = "sha256:3d6f3462bec0c260caadf93fbb377225c126661b779c7d9ab99b6dad5ca10db9"}, + {file = "types_pyOpenSSL-23.3.0.20240106-py3-none-any.whl", hash = "sha256:47a7eedbd18b7bcad17efebf1c53416148f5a173918a6d75027e75e32fe039ae"}, ] [package.dependencies] @@ -3225,24 +3249,24 @@ cryptography = ">=35.0.0" [[package]] name = "types-python-dateutil" -version = "2.8.19.14" +version = "2.8.19.20240106" description = "Typing stubs for python-dateutil" optional = false -python-versions = "*" +python-versions = ">=3.8" files = [ - {file = "types-python-dateutil-2.8.19.14.tar.gz", hash = "sha256:1f4f10ac98bb8b16ade9dbee3518d9ace017821d94b057a425b069f834737f4b"}, - {file = "types_python_dateutil-2.8.19.14-py3-none-any.whl", hash = "sha256:f977b8de27787639986b4e28963263fd0e5158942b3ecef91b9335c130cb1ce9"}, + {file = "types-python-dateutil-2.8.19.20240106.tar.gz", hash = "sha256:1f8db221c3b98e6ca02ea83a58371b22c374f42ae5bbdf186db9c9a76581459f"}, + {file = "types_python_dateutil-2.8.19.20240106-py3-none-any.whl", hash = "sha256:efbbdc54590d0f16152fa103c9879c7d4a00e82078f6e2cf01769042165acaa2"}, ] [[package]] name = "types-redis" -version = "4.6.0.11" +version = "4.6.0.20240106" description = "Typing stubs for redis" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "types-redis-4.6.0.11.tar.gz", hash = "sha256:c8cfc84635183deca2db4a528966c5566445fd3713983f0034fb0f5a09e0890d"}, - {file = "types_redis-4.6.0.11-py3-none-any.whl", hash = "sha256:94fc61118601fb4f79206b33b9f4344acff7ca1d7bba67834987fb0efcf6a770"}, + {file = "types-redis-4.6.0.20240106.tar.gz", hash = "sha256:2b2fa3a78f84559616242d23f86de5f4130dfd6c3b83fb2d8ce3329e503f756e"}, + {file = "types_redis-4.6.0.20240106-py3-none-any.whl", hash = "sha256:912de6507b631934bd225cdac310b04a58def94391003ba83939e5a10e99568d"}, ] [package.dependencies] @@ -3251,13 +3275,13 @@ types-pyOpenSSL = "*" [[package]] name = "types-requests" -version = "2.31.0.20231231" +version = "2.31.0.20240106" description = "Typing stubs for requests" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "types-requests-2.31.0.20231231.tar.gz", hash = "sha256:0f8c0c9764773384122813548d9eea92a5c4e1f33ed54556b508968ec5065cee"}, - {file = "types_requests-2.31.0.20231231-py3-none-any.whl", hash = "sha256:2e2230c7bc8dd63fa3153c1c0ae335f8a368447f0582fc332f17d54f88e69027"}, + {file = "types-requests-2.31.0.20240106.tar.gz", hash = "sha256:0e1c731c17f33618ec58e022b614a1a2ecc25f7dc86800b36ef341380402c612"}, + {file = "types_requests-2.31.0.20240106-py3-none-any.whl", hash = "sha256:da997b3b6a72cc08d09f4dba9802fdbabc89104b35fe24ee588e674037689354"}, ] [package.dependencies] @@ -3372,13 +3396,13 @@ tooling-extras = ["pyaml (>=23.7.0)", "pypandoc-binary (>=1.11)", "pytest (>=7.4 [[package]] name = "wcwidth" -version = "0.2.12" +version = "0.2.13" description = "Measures the displayed width of unicode strings in a terminal" optional = false python-versions = "*" files = [ - {file = "wcwidth-0.2.12-py2.py3-none-any.whl", hash = "sha256:f26ec43d96c8cbfed76a5075dac87680124fa84e0855195a6184da9c187f133c"}, - {file = "wcwidth-0.2.12.tar.gz", hash = "sha256:f01c104efdf57971bcb756f054dd58ddec5204dd15fa31d6503ea57947d97c02"}, + {file = "wcwidth-0.2.13-py2.py3-none-any.whl", hash = "sha256:3da69048e4540d84af32131829ff948f1e022c1c6bdb8d6102117aac784f6859"}, + {file = "wcwidth-0.2.13.tar.gz", hash = "sha256:72ea0c06399eb286d978fdedb6923a9eb47e1c486ce63e9b4e64fc18303972b5"}, ] [[package]] @@ -3540,4 +3564,4 @@ virustotal = ["validators"] [metadata] lock-version = "2.0" python-versions = "^3.8" -content-hash = "85a1cc6f45b693da2ec5c9a7b1a72085c3a2da96a7e358623b3eeb41ea89e339" +content-hash = "096b132456e7298b277cc4a78773b394516e649d44aa12eb86d8a2ba7704429b" diff --git a/pyproject.toml b/pyproject.toml index 48dbc86..d64a99c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -54,7 +54,7 @@ beautifulsoup4 = {version = "^4.12.2", optional = true} validators = {version = "^0.22.0", optional = true} sphinx-autodoc-typehints = {version = "^1.25.2", optional = true} recommonmark = {version = "^0.7.1", optional = true} -reportlab = {version = "^4.0.8", optional = true} +reportlab = {version = "^4.0.9", optional = true} pyfaup = {version = "^1.2", optional = true} publicsuffixlist = {version = "^0.10.0.20231214", optional = true} urllib3 = {extras = ["brotli"], version = "*", optional = true} @@ -78,12 +78,13 @@ requests-mock = "^1.11.0" mypy = "^1.8.0" ipython = [ {version = "<8.13.0", python = "<3.9"}, - {version = "^8.13.0", python = ">=3.9"} + {version = "^8.18.0", python = ">=3.9"}, + {version = "^8.19.0", python = ">=3.10"} ] jupyterlab = "^4.0.10" -types-requests = "^2.31.0.20231231" -types-python-dateutil = "^2.8.19.14" -types-redis = "^4.6.0.11" +types-requests = "^2.31.0.20240106" +types-python-dateutil = "^2.8.19.20240106" +types-redis = "^4.6.0.20240106" types-Flask = "^1.1.6" pytest-cov = "^4.1.0" From dba0c8815476e6cae3f0bb3e6ee061e0a78faee1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Vinot?= Date: Wed, 10 Jan 2024 11:48:47 +0100 Subject: [PATCH 31/80] fix: Add missing wheel --- poetry.lock | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/poetry.lock b/poetry.lock index f6d1197..1dada82 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1230,6 +1230,7 @@ optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*, !=3.6.*" files = [ {file = "jsonpointer-2.4-py2.py3-none-any.whl", hash = "sha256:15d51bba20eea3165644553647711d150376234112651b4f1811022aecad7d7a"}, + {file = "jsonpointer-2.4.tar.gz", hash = "sha256:585cee82b70211fa9e6043b7bb89db6e1aa49524340dde8ad6b63206ea689d88"}, ] [[package]] @@ -1562,6 +1563,16 @@ files = [ {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:5bbe06f8eeafd38e5d0a4894ffec89378b6c6a625ff57e3028921f8ff59318ac"}, {file = "MarkupSafe-2.1.3-cp311-cp311-win32.whl", hash = "sha256:dd15ff04ffd7e05ffcb7fe79f1b98041b8ea30ae9234aed2a9168b5797c3effb"}, {file = "MarkupSafe-2.1.3-cp311-cp311-win_amd64.whl", hash = "sha256:134da1eca9ec0ae528110ccc9e48041e0828d79f24121a1a146161103c76e686"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:f698de3fd0c4e6972b92290a45bd9b1536bffe8c6759c62471efaa8acb4c37bc"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:aa57bd9cf8ae831a362185ee444e15a93ecb2e344c8e52e4d721ea3ab6ef1823"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ffcc3f7c66b5f5b7931a5aa68fc9cecc51e685ef90282f4a82f0f5e9b704ad11"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47d4f1c5f80fc62fdd7777d0d40a2e9dda0a05883ab11374334f6c4de38adffd"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1f67c7038d560d92149c060157d623c542173016c4babc0c1913cca0564b9939"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:9aad3c1755095ce347e26488214ef77e0485a3c34a50c5a5e2471dff60b9dd9c"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:14ff806850827afd6b07a5f32bd917fb7f45b046ba40c57abdb636674a8b559c"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8f9293864fe09b8149f0cc42ce56e3f0e54de883a9de90cd427f191c346eb2e1"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-win32.whl", hash = "sha256:715d3562f79d540f251b99ebd6d8baa547118974341db04f5ad06d5ea3eb8007"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-win_amd64.whl", hash = "sha256:1b8dd8c3fd14349433c79fa8abeb573a55fc0fdd769133baac1f5e07abf54aeb"}, {file = "MarkupSafe-2.1.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:8e254ae696c88d98da6555f5ace2279cf7cd5b3f52be2b5cf97feafe883b58d2"}, {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb0932dc158471523c9637e807d9bfb93e06a95cbf010f1a38b98623b929ef2b"}, {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9402b03f1a1b4dc4c19845e5c749e3ab82d5078d16a2a4c2cd2df62d57bb0707"}, @@ -2169,6 +2180,8 @@ files = [ {file = "pydeep2-0.5.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2283893e25826b547dd1e5c71a010e86ddfd7270e2f2b8c90973c1d7984c7eb7"}, {file = "pydeep2-0.5.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f248e3161deb53d46a9368a7c164e36d83004faf2f11625d47a5cf23a6bdd2cb"}, {file = "pydeep2-0.5.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a13fca9be89a9fa8d92a4f49d7b9191eef94555f8ddf030fb2be4c8c15ad618c"}, + {file = "pydeep2-0.5.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d1cb4757db97ac15ddf034c21cd6bab984f841586b6d53984e63c9a7803b2cd4"}, + {file = "pydeep2-0.5.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7809a1d6640bdbee68f075d53229d05229e11b4711f232728dd540f68e6483a4"}, {file = "pydeep2-0.5.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0fedc1c9660cb5d0b73ad0b5f1dbffe16990e6721cbfc6454571a4b9882d0ea4"}, {file = "pydeep2-0.5.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7ca68f7d63e2ef510d410d20b223e8e97df41707fb50c4c526b6dd1d8698d9e6"}, {file = "pydeep2-0.5.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:199d05d8b4b7544509a2ba4802ead4b41dfe7859e0ecea9d9be9e41939f11660"}, @@ -2354,6 +2367,7 @@ files = [ {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"}, @@ -2361,8 +2375,15 @@ files = [ {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"}, @@ -2379,6 +2400,7 @@ files = [ {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"}, @@ -2386,6 +2408,7 @@ files = [ {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"}, From b8af5a3964df9d7b4eb1b49de818039b53d6bea2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Vinot?= Date: Wed, 10 Jan 2024 11:53:41 +0100 Subject: [PATCH 32/80] fix: Rollback tests on python 3.12 as lief is not supported yet. --- .github/workflows/pytest.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pytest.yml b/.github/workflows/pytest.yml index f61ef93..febc048 100644 --- a/.github/workflows/pytest.yml +++ b/.github/workflows/pytest.yml @@ -13,7 +13,7 @@ jobs: strategy: fail-fast: false matrix: - python-version: [3.8, 3.9, '3.10', '3.11', '3.12'] + python-version: [3.8, 3.9, '3.10', '3.11'] steps: From d329a5e095dd9e7412ab72f570a453e84cf628b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Vinot?= Date: Wed, 10 Jan 2024 14:08:43 +0100 Subject: [PATCH 33/80] new: relationship_type in tag Fix https://github.com/MISP/MISP/issues/9483 --- pymisp/api.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/pymisp/api.py b/pymisp/api.py index 85f6b00..755117a 100644 --- a/pymisp/api.py +++ b/pymisp/api.py @@ -3536,12 +3536,14 @@ class PyMISP: raise PyMISPError('The misp_entity must be MISPEvent, MISPObject or MISPAttribute') - def tag(self, misp_entity: Union[AbstractMISP, str, dict], tag: Union[MISPTag, str], local: bool = False) -> Dict: + def tag(self, misp_entity: Union[AbstractMISP, str, dict], tag: Union[MISPTag, str], + local: bool = False, relationship_type: Optional[str] = None) -> Dict: """Tag an event or an attribute. :param misp_entity: a MISPEvent, a MISP Attribute, or a UUID :param tag: tag to add :param local: whether to tag locally + :param relationship_type: Type of relationship between the tag and the attribute or event """ uuid = get_uuid_or_id_from_abstract_misp(misp_entity) if isinstance(tag, MISPTag): @@ -3549,6 +3551,8 @@ class PyMISP: else: tag_name = tag to_post = {'uuid': uuid, 'tag': tag_name, 'local': local} + if relationship_type: + to_post['relationship_type'] = relationship_type response = self._prepare_request('POST', 'tags/attachTagToObject', data=to_post) return self._check_json_response(response) From 80a0b3e8a8c21c4aea1a0606d9922d730c56792d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 11 Jan 2024 19:51:02 +0000 Subject: [PATCH 34/80] build(deps): bump jinja2 from 3.1.2 to 3.1.3 Bumps [jinja2](https://github.com/pallets/jinja) from 3.1.2 to 3.1.3. - [Release notes](https://github.com/pallets/jinja/releases) - [Changelog](https://github.com/pallets/jinja/blob/main/CHANGES.rst) - [Commits](https://github.com/pallets/jinja/compare/3.1.2...3.1.3) --- updated-dependencies: - dependency-name: jinja2 dependency-type: indirect ... Signed-off-by: dependabot[bot] --- poetry.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/poetry.lock b/poetry.lock index 1dada82..69be550 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1193,13 +1193,13 @@ testing = ["Django", "attrs", "colorama", "docopt", "pytest (<7.0.0)"] [[package]] name = "jinja2" -version = "3.1.2" +version = "3.1.3" description = "A very fast and expressive template engine." optional = false python-versions = ">=3.7" files = [ - {file = "Jinja2-3.1.2-py3-none-any.whl", hash = "sha256:6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61"}, - {file = "Jinja2-3.1.2.tar.gz", hash = "sha256:31351a702a408a9e7595a8fc6150fc3f43bb6bf7e319770cbc0db9df9437e852"}, + {file = "Jinja2-3.1.3-py3-none-any.whl", hash = "sha256:7d6d50dd97d52cbc355597bd845fabfbac3f551e1f99619e39a35ce8c370b5fa"}, + {file = "Jinja2-3.1.3.tar.gz", hash = "sha256:ac8bd6544d4bb2c9792bf3a159e80bba8fda7f07e81bc3aed565432d5925ba90"}, ] [package.dependencies] From ac0421a7b110cfc0c79144c57d02ee9f6f62edc8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Vinot?= Date: Thu, 11 Jan 2024 21:43:47 +0100 Subject: [PATCH 35/80] chg: Bump deps --- poetry.lock | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/poetry.lock b/poetry.lock index 1dada82..9620789 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1193,13 +1193,13 @@ testing = ["Django", "attrs", "colorama", "docopt", "pytest (<7.0.0)"] [[package]] name = "jinja2" -version = "3.1.2" +version = "3.1.3" description = "A very fast and expressive template engine." optional = false python-versions = ">=3.7" files = [ - {file = "Jinja2-3.1.2-py3-none-any.whl", hash = "sha256:6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61"}, - {file = "Jinja2-3.1.2.tar.gz", hash = "sha256:31351a702a408a9e7595a8fc6150fc3f43bb6bf7e319770cbc0db9df9437e852"}, + {file = "Jinja2-3.1.3-py3-none-any.whl", hash = "sha256:7d6d50dd97d52cbc355597bd845fabfbac3f551e1f99619e39a35ce8c370b5fa"}, + {file = "Jinja2-3.1.3.tar.gz", hash = "sha256:ac8bd6544d4bb2c9792bf3a159e80bba8fda7f07e81bc3aed565432d5925ba90"}, ] [package.dependencies] @@ -1364,13 +1364,13 @@ jupyter-server = ">=1.1.2" [[package]] name = "jupyter-server" -version = "2.12.3" +version = "2.12.4" description = "The backend—i.e. core services, APIs, and REST endpoints—to Jupyter web applications." optional = false python-versions = ">=3.8" files = [ - {file = "jupyter_server-2.12.3-py3-none-any.whl", hash = "sha256:6f85310ea5e6068568a521f079fba99d8d17e4884dd1d602ab0f43b3115204a8"}, - {file = "jupyter_server-2.12.3.tar.gz", hash = "sha256:a1d2d51e497b1a6256c48b6940b0dd49b2553981baf1690077c37792f1fa23a1"}, + {file = "jupyter_server-2.12.4-py3-none-any.whl", hash = "sha256:a125ae18a60de568f78f55c84dd58759901a18ef279abf0418ac220653ca1320"}, + {file = "jupyter_server-2.12.4.tar.gz", hash = "sha256:41f4a1e6b912cc24a7c6c694851b37d3d8412b180f43d72315fe422cb2b85cc2"}, ] [package.dependencies] @@ -1727,13 +1727,13 @@ test = ["flaky", "ipykernel (>=6.19.3)", "ipython", "ipywidgets", "nbconvert (>= [[package]] name = "nbconvert" -version = "7.14.0" +version = "7.14.1" description = "Converting Jupyter Notebooks" optional = false python-versions = ">=3.8" files = [ - {file = "nbconvert-7.14.0-py3-none-any.whl", hash = "sha256:483dde47facdaa4875903d651305ad53cd76e2255ae3c61efe412a95f2d22a24"}, - {file = "nbconvert-7.14.0.tar.gz", hash = "sha256:92b9a44b63e5a7fb4f6fa0ef41261e35c16925046ccd1c04a5c8099bf100476e"}, + {file = "nbconvert-7.14.1-py3-none-any.whl", hash = "sha256:aa83e3dd27ea38d0c1d908e3ce9518d15fa908dd30521b6d5040bd23f33fffb0"}, + {file = "nbconvert-7.14.1.tar.gz", hash = "sha256:20cba10e0448dc76b3bebfe1adf923663e3b98338daf77b97b42511ef5a88618"}, ] [package.dependencies] From 8c23a2def78e2e715084f6bc871ffa0a051d3467 Mon Sep 17 00:00:00 2001 From: Jakub Onderka Date: Tue, 16 Jan 2024 21:56:34 +0100 Subject: [PATCH 36/80] chg: [internal] User faster method to convert bytes to str --- pymisp/abstract.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pymisp/abstract.py b/pymisp/abstract.py index 8a4be01..88198af 100644 --- a/pymisp/abstract.py +++ b/pymisp/abstract.py @@ -247,8 +247,9 @@ class AbstractMISP(MutableMapping, MISPFileCache, metaclass=ABCMeta): option |= orjson.OPT_SORT_KEYS if indent: option |= orjson.OPT_INDENT_2 - - return dumps(self, default=pymisp_json_default, option=option).decode("utf-8") + # orjson dumps method returns bytes instead of bytes, to keep compatibility with json + # we have to convert output to str + return str(dumps(self, default=pymisp_json_default, option=option)) return dumps(self, default=pymisp_json_default, sort_keys=sort_keys, indent=indent) From 292948aa580dd19a04f676f31d0e3697f52d88fe Mon Sep 17 00:00:00 2001 From: Jakub Onderka Date: Tue, 16 Jan 2024 21:57:06 +0100 Subject: [PATCH 37/80] chg: [internal] Simplify code --- pymisp/api.py | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/pymisp/api.py b/pymisp/api.py index 85f6b00..53dab93 100644 --- a/pymisp/api.py +++ b/pymisp/api.py @@ -69,7 +69,7 @@ def get_uuid_or_id_from_abstract_misp(obj: Union[AbstractMISP, int, str, UUID, d if isinstance(obj, (int, str)): return obj - if isinstance(obj, dict) and len(obj.keys()) == 1: + if isinstance(obj, dict) and len(obj) == 1: # We have an object in that format: {'Event': {'id': 2, ...}} # We need to get the content of that dictionary obj = obj[list(obj.keys())[0]] @@ -186,6 +186,7 @@ class PyMISP: self.__session.headers['Accept-Encoding'] = ', '.join(('br', 'gzip', 'deflate')) if http_headers: self.__session.headers.update(http_headers) + self._user_agent = f'PyMISP {__version__} - Python {".".join(str(x) for x in sys.version_info[:2])}' self.global_pythonify = False @@ -2622,10 +2623,10 @@ class PyMISP: ''' - return_formats = ['openioc', 'json', 'xml', 'suricata', 'snort', 'text', 'rpz', 'csv', 'cache', 'stix-xml', - 'stix', 'stix2', 'yara', 'yara-json', 'attack', 'attack-sightings', 'context', 'context-markdown'] + return_formats = ('openioc', 'json', 'xml', 'suricata', 'snort', 'text', 'rpz', 'csv', 'cache', 'stix-xml', + 'stix', 'stix2', 'yara', 'yara-json', 'attack', 'attack-sightings', 'context', 'context-markdown') - if controller not in ['events', 'attributes', 'objects']: + if controller not in ('events', 'attributes', 'objects'): raise ValueError('controller has to be in {}'.format(', '.join(['events', 'attributes', 'objects']))) # Deprecated stuff / synonyms @@ -2996,7 +2997,7 @@ class PyMISP: query.pop('pythonify') if log_id is not None: query['id'] = query.pop('log_id') - if created is not None and isinstance(created, (datetime)): + if created is not None and isinstance(created, datetime): query['created'] = query.pop('created').timestamp() response = self._prepare_request('POST', 'admin/logs/index', data=query) @@ -3349,7 +3350,7 @@ class PyMISP: """ query: Dict[str, Any] = {'setting': user_setting} if isinstance(value, dict): - value = dumps(value).decode("utf-8") if HAS_ORJSON else dumps(value) + value = str(dumps(value)) if HAS_ORJSON else dumps(value) query['value'] = value if user: query['user_id'] = get_uuid_or_id_from_abstract_misp(user) @@ -3739,7 +3740,7 @@ class PyMISP: data = {k: v for k, v in data.items() if v is not None} d = dumps(data, default=pymisp_json_default) - logger.debug(f'{request_type} - {url}') + logger.debug('%s - %s', request_type, url) if d is not None: logger.debug(d) @@ -3749,9 +3750,7 @@ class PyMISP: url = f'{url}/{to_append_url}' req = requests.Request(request_type, url, data=d, params=params) - user_agent = f'PyMISP {__version__} - Python {".".join(str(x) for x in sys.version_info[:2])}' - if self.tool: - user_agent = f'{user_agent} - {self.tool}' + user_agent = f'{self._user_agent} - {self.tool}' if self.tool else self._user_agent req.auth = self.auth prepped = self.__session.prepare_request(req) prepped.headers.update( From 0562c63cec7e7dbdacf576b7fb7cc840a818a896 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Vinot?= Date: Wed, 17 Jan 2024 13:13:14 +0100 Subject: [PATCH 38/80] chg: Initial changes to use new annotations --- mypy.ini | 16 +- pymisp/__init__.py | 4 +- pymisp/abstract.py | 61 +- pymisp/api.py | 754 +++++++++++++------------ pymisp/exceptions.py | 4 +- pymisp/mispevent.py | 401 ++++++------- pymisp/tools/__init__.py | 2 + pymisp/tools/_psl_faup.py | 7 +- pymisp/tools/abstractgenerator.py | 7 +- pymisp/tools/asnobject.py | 3 +- pymisp/tools/create_misp_object.py | 5 +- pymisp/tools/csvloader.py | 5 +- pymisp/tools/domainipobject.py | 3 +- pymisp/tools/elfobject.py | 13 +- pymisp/tools/emailobject.py | 37 +- pymisp/tools/ext_lookups.py | 3 +- pymisp/tools/fail2banobject.py | 3 +- pymisp/tools/feed.py | 5 +- pymisp/tools/fileobject.py | 7 +- pymisp/tools/genericgenerator.py | 5 +- pymisp/tools/geolocationobject.py | 3 +- pymisp/tools/git_vuln_finder_object.py | 3 +- pymisp/tools/load_warninglists.py | 3 +- pymisp/tools/machoobject.py | 13 +- pymisp/tools/microblogobject.py | 3 +- pymisp/tools/neo4j.py | 4 +- pymisp/tools/openioc.py | 5 +- pymisp/tools/peobject.py | 15 +- pymisp/tools/reportlab_generator.py | 11 +- pymisp/tools/sbsignatureobject.py | 3 +- pymisp/tools/sshauthkeyobject.py | 7 +- pymisp/tools/stix.py | 2 +- pymisp/tools/update_objects.py | 3 +- pymisp/tools/urlobject.py | 3 +- pymisp/tools/vehicleobject.py | 4 +- pymisp/tools/vtreportobject.py | 9 +- tests/testlive_comprehensive.py | 9 +- tests/testlive_sync.py | 9 +- 38 files changed, 731 insertions(+), 723 deletions(-) diff --git a/mypy.ini b/mypy.ini index 78ad923..9c8481b 100644 --- a/mypy.ini +++ b/mypy.ini @@ -1,6 +1,16 @@ [mypy] -ignore_errors = False - +strict = True +warn_return_any = False show_error_context = True pretty = True -exclude = pymisp/data|example|docs +exclude = feed-generator|examples + +# Stuff to remove gradually +disallow_untyped_defs = False +disallow_untyped_calls = False +check_untyped_defs = False +disable_error_code = attr-defined,type-arg,no-untyped-def + + +[mypy-docs.source.*] +ignore_errors = True diff --git a/pymisp/__init__.py b/pymisp/__init__.py index e3f07c0..a38ad3c 100644 --- a/pymisp/__init__.py +++ b/pymisp/__init__.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import logging import sys import warnings @@ -59,4 +61,4 @@ try: pass logger.debug('pymisp loaded properly') except ImportError as e: - logger.warning('Unable to load pymisp properly: {}'.format(e)) + logger.warning(f'Unable to load pymisp properly: {e}') diff --git a/pymisp/abstract.py b/pymisp/abstract.py index 8a4be01..86a97a3 100644 --- a/pymisp/abstract.py +++ b/pymisp/abstract.py @@ -1,4 +1,7 @@ #!/usr/bin/env python3 + +from __future__ import annotations + import logging from datetime import date, datetime from deprecated import deprecated # type: ignore @@ -6,14 +9,14 @@ from json import JSONEncoder from uuid import UUID from abc import ABCMeta from enum import Enum -from typing import Union, Optional, Any, Dict, List, Set, Mapping +from typing import Any, Mapping from collections.abc import MutableMapping from functools import lru_cache from pathlib import Path try: import orjson # type: ignore - from orjson import loads, dumps # type: ignore + from orjson import loads, dumps HAS_ORJSON = True except ImportError: from json import loads, dumps @@ -30,12 +33,12 @@ with (resources_path / 'describeTypes.json').open('rb') as f: describe_types = loads(f.read())['result'] -class MISPFileCache(object): +class MISPFileCache: # cache up to 150 JSON structures in class attribute @staticmethod @lru_cache(maxsize=150) - def _load_json(path: Path) -> Optional[dict]: + def _load_json(path: Path) -> dict | None: if not path.exists(): return None with path.open('rb') as f: @@ -65,7 +68,7 @@ class Analysis(Enum): completed = 2 -def _int_to_str(d: Dict[str, Any]) -> Dict[str, Any]: +def _int_to_str(d: dict[str, Any]) -> dict[str, Any]: # transform all integer back to string for k, v in d.items(): if isinstance(v, dict): @@ -94,7 +97,7 @@ class AbstractMISP(MutableMapping, MISPFileCache, metaclass=ABCMeta): __misp_objects_path = misp_objects_path __describe_types = describe_types - def __init__(self, **kwargs: Dict): + def __init__(self, **kwargs: dict): """Abstract class for all the MISP objects. NOTE: Every method in every classes inheriting this one are doing changes in memory and do not modify data on a remote MISP instance. @@ -103,9 +106,9 @@ class AbstractMISP(MutableMapping, MISPFileCache, metaclass=ABCMeta): """ super().__init__() self.__edited: bool = True # As we create a new object, we assume it is edited - self.__not_jsonable: List[str] = [] - self._fields_for_feed: Set - self.__self_defined_describe_types: Optional[Dict] = None + self.__not_jsonable: list[str] = [] + self._fields_for_feed: set + self.__self_defined_describe_types: dict | None = None self.uuid: str if kwargs.get('force_timestamps') is not None: @@ -115,13 +118,13 @@ class AbstractMISP(MutableMapping, MISPFileCache, metaclass=ABCMeta): self.__force_timestamps = False @property - def describe_types(self) -> Dict: + def describe_types(self) -> dict: if self.__self_defined_describe_types: return self.__self_defined_describe_types return self.__describe_types @describe_types.setter - def describe_types(self, describe_types: Dict): + def describe_types(self, describe_types: dict): self.__self_defined_describe_types = describe_types @property @@ -133,7 +136,7 @@ class AbstractMISP(MutableMapping, MISPFileCache, metaclass=ABCMeta): return self.__misp_objects_path @misp_objects_path.setter - def misp_objects_path(self, misp_objects_path: Union[str, Path]): + def misp_objects_path(self, misp_objects_path: str | Path): if isinstance(misp_objects_path, str): misp_objects_path = Path(misp_objects_path) self.__misp_objects_path = misp_objects_path @@ -155,7 +158,7 @@ class AbstractMISP(MutableMapping, MISPFileCache, metaclass=ABCMeta): """Add entries to the __not_jsonable list""" self.__not_jsonable += args - def set_not_jsonable(self, args: List[str]) -> None: + def set_not_jsonable(self, args: list[str]) -> None: """Set __not_jsonable to a new list""" self.__not_jsonable = args @@ -171,7 +174,7 @@ class AbstractMISP(MutableMapping, MISPFileCache, metaclass=ABCMeta): """Load a JSON string""" self.from_dict(**loads(json_string)) - def to_dict(self, json_format: bool = False) -> Dict: + def to_dict(self, json_format: bool = False) -> dict: """Dump the class to a dictionary. This method automatically removes the timestamp recursively in every object that has been edited is order to let MISP update the event accordingly.""" @@ -213,15 +216,15 @@ class AbstractMISP(MutableMapping, MISPFileCache, metaclass=ABCMeta): to_return = _int_to_str(to_return) return to_return - def jsonable(self) -> Dict: + def jsonable(self) -> dict: """This method is used by the JSON encoder""" return self.to_dict() - def _to_feed(self) -> Dict: + def _to_feed(self) -> dict: if not hasattr(self, '_fields_for_feed') or not self._fields_for_feed: raise PyMISPError('Unable to export in the feed format, _fields_for_feed is missing.') - if hasattr(self, '_set_default') and callable(self._set_default): # type: ignore - self._set_default() # type: ignore + if hasattr(self, '_set_default') and callable(self._set_default): + self._set_default() to_return = {} for field in sorted(self._fields_for_feed): if getattr(self, field, None) is not None: @@ -235,11 +238,11 @@ class AbstractMISP(MutableMapping, MISPFileCache, metaclass=ABCMeta): if field in ['data', 'first_seen', 'last_seen', 'deleted']: # special fields continue - raise PyMISPError('The field {} is required in {} when generating a feed.'.format(field, self.__class__.__name__)) + raise PyMISPError(f'The field {field} is required in {self.__class__.__name__} when generating a feed.') to_return = _int_to_str(to_return) return to_return - def to_json(self, sort_keys: bool = False, indent: Optional[int] = None) -> str: + def to_json(self, sort_keys: bool = False, indent: int | None = None) -> str: """Dump recursively any class of type MISPAbstract to a json string""" if HAS_ORJSON: option = 0 @@ -320,14 +323,14 @@ class AbstractMISP(MutableMapping, MISPFileCache, metaclass=ABCMeta): self.__edited = True super().__setattr__(name, value) - def _datetime_to_timestamp(self, d: Union[int, float, str, datetime]) -> int: + def _datetime_to_timestamp(self, d: int | float | str | datetime) -> int: """Convert a datetime object to a timestamp (int)""" if isinstance(d, (int, float, str)): # Assume we already have a timestamp return int(d) return int(d.timestamp()) - def _add_tag(self, tag: Optional[Union[str, 'MISPTag', Mapping]] = None, **kwargs): + def _add_tag(self, tag: str | MISPTag | Mapping | None = None, **kwargs): """Add a tag to the attribute (by name or a MISPTag object)""" if isinstance(tag, str): misp_tag = MISPTag() @@ -347,7 +350,7 @@ class AbstractMISP(MutableMapping, MISPFileCache, metaclass=ABCMeta): self.edited = True return misp_tag - def _set_tags(self, tags: List['MISPTag']): + def _set_tags(self, tags: list[MISPTag]): """Set a list of prepared MISPTag.""" if all(isinstance(x, MISPTag) for x in tags): self.Tag = tags @@ -363,19 +366,19 @@ class AbstractMISP(MutableMapping, MISPFileCache, metaclass=ABCMeta): return False def __repr__(self) -> str: - return '<{self.__class__.__name__} - please define me>'.format(self=self) + return f'<{self.__class__.__name__} - please define me>' class MISPTag(AbstractMISP): _fields_for_feed: set = {'name', 'colour', 'relationship_type', 'local'} - def __init__(self, **kwargs: Dict): + def __init__(self, **kwargs: dict): super().__init__(**kwargs) self.name: str self.exportable: bool self.local: bool - self.relationship_type: Optional[str] + self.relationship_type: str | None def from_dict(self, **kwargs): if kwargs.get('Tag'): @@ -390,7 +393,7 @@ class MISPTag(AbstractMISP): if not hasattr(self, 'local'): self.local = False - def _to_feed(self, with_local: bool = True) -> Dict: + def _to_feed(self, with_local: bool = True) -> dict: if hasattr(self, 'exportable') and not self.exportable: return {} if with_local is False and hasattr(self, 'local') and self.local: @@ -404,11 +407,11 @@ class MISPTag(AbstractMISP): def __repr__(self) -> str: if hasattr(self, 'name'): return '<{self.__class__.__name__}(name={self.name})>'.format(self=self) - return '<{self.__class__.__name__}(NotInitialized)>'.format(self=self) + return f'<{self.__class__.__name__}(NotInitialized)>' # UUID, datetime, date and Enum is serialized by ORJSON by default -def pymisp_json_default(obj: Union[AbstractMISP, datetime, date, Enum, UUID]) -> Union[Dict, str]: +def pymisp_json_default(obj: AbstractMISP | datetime | date | Enum | UUID) -> dict | str: if isinstance(obj, AbstractMISP): return obj.jsonable() elif isinstance(obj, (datetime, date)): diff --git a/pymisp/api.py b/pymisp/api.py index 755117a..eaadb99 100644 --- a/pymisp/api.py +++ b/pymisp/api.py @@ -1,4 +1,6 @@ -from typing import TypeVar, Optional, Tuple, List, Dict, Union, Any, Mapping, Iterable, MutableMapping +from __future__ import annotations + +from typing import TypeVar, Any, Mapping, Iterable, MutableMapping from datetime import date, datetime import csv from pathlib import Path @@ -11,7 +13,7 @@ from uuid import UUID import warnings import sys import copy -import urllib3 # type: ignore +import urllib3 from io import BytesIO, StringIO try: @@ -46,23 +48,23 @@ if sys.platform == 'linux': try: # cached_property exists since Python 3.8 - from functools import cached_property # type: ignore + from functools import cached_property except ImportError: from functools import lru_cache def cached_property(func): # type: ignore - return property(lru_cache()(func)) + return property(lru_cache(func)) SearchType = TypeVar('SearchType', str, int) # str: string to search / list: values to search (OR) / dict: {'OR': [list], 'NOT': [list], 'AND': [list]} -SearchParameterTypes = TypeVar('SearchParameterTypes', str, List[Union[str, int]], Dict[str, Union[str, int]]) +SearchParameterTypes = TypeVar('SearchParameterTypes', str, list[str | int], dict[str, str | int]) ToIDSType = TypeVar('ToIDSType', str, int, bool) logger = logging.getLogger('pymisp') -def get_uuid_or_id_from_abstract_misp(obj: Union[AbstractMISP, int, str, UUID, dict]) -> Union[str, int]: +def get_uuid_or_id_from_abstract_misp(obj: AbstractMISP | int | str | UUID | dict) -> str | int: """Extract the relevant ID accordingly to the given type passed as parameter""" if isinstance(obj, UUID): return str(obj) @@ -94,11 +96,11 @@ def get_uuid_or_id_from_abstract_misp(obj: Union[AbstractMISP, int, str, UUID, d def register_user(misp_url: str, email: str, - organisation: Optional[Union[MISPOrganisation, int, str, UUID]] = None, - org_id: Optional[str] = None, org_name: Optional[str] = None, - message: Optional[str] = None, custom_perms: Optional[str] = None, + organisation: MISPOrganisation | int | str | UUID | None = None, + org_id: str | None = None, org_name: str | None = None, + message: str | None = None, custom_perms: str | None = None, perm_sync: bool = False, perm_publish: bool = False, perm_admin: bool = False, - verify: bool = True) -> Dict: + verify: bool = True) -> dict: """Ask for the creation of an account for the user with the given email address""" data = copy.deepcopy(locals()) if organisation: @@ -129,7 +131,7 @@ def brotli_supported() -> bool: patch = 0 else: major, minor, patch = version_splitted # type: ignore - major, minor, patch = int(major), int(minor), int(patch) # type: ignore + major, minor, patch = int(major), int(minor), int(patch) urllib3_with_brotli = (major == 1 and ((minor == 25 and patch >= 1) or (minor >= 26))) or major >= 2 if not urllib3_with_brotli: @@ -159,11 +161,11 @@ class PyMISP: :param timeout: Timeout, as described here: https://requests.readthedocs.io/en/master/user/advanced/#timeouts """ - def __init__(self, url: str, key: str, ssl: Union[bool, str] = True, debug: bool = False, proxies: Optional[MutableMapping[str, str]] = None, - cert: Optional[Union[str, Tuple[str, str]]] = None, auth: Optional[AuthBase] = None, tool: str = '', - timeout: Optional[Union[float, Tuple[float, float]]] = None, - http_headers: Optional[Dict[str, str]] = None, - https_adapter: Optional[requests.adapters.BaseAdapter] = None + def __init__(self, url: str, key: str, ssl: bool | str = True, debug: bool = False, proxies: MutableMapping[str, str] | None = None, + cert: str | tuple[str, str] | None = None, auth: AuthBase | None = None, tool: str = '', + timeout: float | tuple[float, float] | None = None, + http_headers: dict[str, str] | None = None, + https_adapter: requests.adapters.BaseAdapter | None = None ): if not url: @@ -173,12 +175,12 @@ class PyMISP: self.root_url: str = url self.key: str = key - self.ssl: Union[bool, str] = ssl - self.proxies: Optional[MutableMapping[str, str]] = proxies - self.cert: Optional[Union[str, Tuple[str, str]]] = cert - self.auth: Optional[AuthBase] = auth + self.ssl: bool | str = ssl + self.proxies: MutableMapping[str, str] | None = proxies + self.cert: str | tuple[str, str] | None = cert + self.auth: AuthBase | None = auth self.tool: str = tool - self.timeout: Optional[Union[float, Tuple[float, float]]] = timeout + self.timeout: float | tuple[float, float] | None = timeout self.__session = requests.Session() # use one session to keep connection between requests if https_adapter is not None: self.__session.mount('https://', https_adapter) @@ -214,7 +216,7 @@ class PyMISP: # Get the user information self._current_user: MISPUser self._current_role: MISPRole - self._current_user_settings: List[MISPUserSetting] + self._current_user_settings: list[MISPUserSetting] user_infos = self.get_user(pythonify=True, expanded=True) if isinstance(user_infos, dict): # There was an error during the get_user call @@ -240,7 +242,7 @@ class PyMISP: self.category_type_mapping = self.describe_types['category_type_mappings'] self.sane_default = self.describe_types['sane_defaults'] - def remote_acl(self, debug_type: str = 'findMissingFunctionNames') -> Dict: + def remote_acl(self, debug_type: str = 'findMissingFunctionNames') -> dict: """This should return an empty list, unless the ACL is outdated. :param debug_type: printAllFunctionNames, findMissingFunctionNames, or printRoleAccess @@ -249,19 +251,19 @@ class PyMISP: return self._check_json_response(response) @property - def describe_types_local(self) -> Dict: + def describe_types_local(self) -> dict: '''Returns the content of describe types from the package''' return describe_types @property - def describe_types_remote(self) -> Dict: + def describe_types_remote(self) -> dict: '''Returns the content of describe types from the remote instance''' response = self._prepare_request('GET', 'attributes/describeTypes.json') remote_describe_types = self._check_json_response(response) return remote_describe_types['result'] @property - def recommended_pymisp_version(self) -> Dict: + def recommended_pymisp_version(self) -> dict: """Returns the recommended API version from the server""" # Sine MISP 2.4.146 is recommended PyMISP version included in getVersion call misp_version = self.misp_instance_version @@ -272,17 +274,17 @@ class PyMISP: return self._check_json_response(response) @property - def version(self) -> Dict: + def version(self) -> dict: """Returns the version of PyMISP you're currently using""" return {'version': __version__} @property - def pymisp_version_master(self) -> Dict: + def pymisp_version_master(self) -> dict: """PyMISP version as defined in the main repository""" return self.pymisp_version_main @property - def pymisp_version_main(self) -> Dict: + def pymisp_version_main(self) -> dict: """Get the most recent version of PyMISP from github""" r = requests.get('https://raw.githubusercontent.com/MISP/PyMISP/main/pyproject.toml') if r.status_code == 200: @@ -291,13 +293,13 @@ class PyMISP: return {'error': 'Impossible to retrieve the version of the main branch.'} @cached_property - def misp_instance_version(self) -> Dict: + def misp_instance_version(self) -> dict: """Returns the version of the instance.""" response = self._prepare_request('GET', 'servers/getVersion') return self._check_json_response(response) @property - def misp_instance_version_master(self) -> Dict: + def misp_instance_version_master(self) -> dict: """Get the most recent version from github""" r = requests.get('https://raw.githubusercontent.com/MISP/MISP/2.4/VERSION.json') if r.status_code == 200: @@ -305,12 +307,12 @@ class PyMISP: return {'version': '{}.{}.{}'.format(master_version['major'], master_version['minor'], master_version['hotfix'])} return {'error': 'Impossible to retrieve the version of the master branch.'} - def update_misp(self) -> Dict: + def update_misp(self) -> dict: """Trigger a server update""" response = self._prepare_request('POST', 'servers/update') return self._check_json_response(response) - def set_server_setting(self, setting: str, value: Union[str, int, bool], force: bool = False) -> Dict: + def set_server_setting(self, setting: str, value: str | int | bool, force: bool = False) -> dict: """Set a setting on the MISP instance :param setting: server setting name @@ -321,7 +323,7 @@ class PyMISP: response = self._prepare_request('POST', f'servers/serverSettingsEdit/{setting}', data=data) return self._check_json_response(response) - def get_server_setting(self, setting: str) -> Dict: + def get_server_setting(self, setting: str) -> dict: """Get a setting from the MISP instance :param setting: server setting name @@ -329,17 +331,17 @@ class PyMISP: response = self._prepare_request('GET', f'servers/getSetting/{setting}') return self._check_json_response(response) - def server_settings(self) -> Dict: + def server_settings(self) -> dict: """Get all the settings from the server""" response = self._prepare_request('GET', 'servers/serverSettings') return self._check_json_response(response) - def restart_workers(self) -> Dict: + def restart_workers(self) -> dict: """Restart all the workers""" response = self._prepare_request('POST', 'servers/restartWorkers') return self._check_json_response(response) - def db_schema_diagnostic(self) -> Dict: + def db_schema_diagnostic(self) -> dict: """Get the schema diagnostic""" response = self._prepare_request('GET', 'servers/dbSchemaDiagnostic') return self._check_json_response(response) @@ -350,7 +352,7 @@ class PyMISP: # ## BEGIN Event ## - def events(self, pythonify: bool = False) -> Union[Dict, List[MISPEvent]]: + def events(self, pythonify: bool = False) -> dict | list[MISPEvent]: """Get all the events from the MISP instance: https://www.misp-project.org/openapi/#tag/Events/operation/getEvents :param pythonify: Returns a list of PyMISP Objects instead of the plain json output. Warning: it might use a lot of RAM @@ -366,10 +368,10 @@ class PyMISP: to_return.append(e) return to_return - def get_event(self, event: Union[MISPEvent, int, str, UUID], - deleted: Union[bool, int, list] = False, - extended: Union[bool, int] = False, - pythonify: bool = False) -> Union[Dict, MISPEvent]: + def get_event(self, event: MISPEvent | int | str | UUID, + deleted: bool | int | list = False, + extended: bool | int = False, + pythonify: bool = False) -> dict | MISPEvent: """Get an event from a MISP instance. Includes collections like Attribute, EventReport, Feed, Galaxy, Object, Tag, etc. so the response size may be large : https://www.misp-project.org/openapi/#tag/Events/operation/getEventById @@ -396,7 +398,7 @@ class PyMISP: e.load(event_r) return e - def event_exists(self, event: Union[MISPEvent, int, str, UUID]) -> bool: + def event_exists(self, event: MISPEvent | int | str | UUID) -> bool: """Fast check if event exists. :param event: Event to check @@ -405,7 +407,7 @@ class PyMISP: r = self._prepare_request('HEAD', f'events/view/{event_id}') return self._check_head_response(r) - def add_event(self, event: MISPEvent, pythonify: bool = False, metadata: bool = False) -> Union[Dict, MISPEvent]: + def add_event(self, event: MISPEvent, pythonify: bool = False, metadata: bool = False) -> dict | MISPEvent: """Add a new event on a MISP instance: https://www.misp-project.org/openapi/#tag/Events/operation/addEvent :param event: event to add @@ -420,8 +422,8 @@ class PyMISP: e.load(new_event) return e - def update_event(self, event: MISPEvent, event_id: Optional[int] = None, pythonify: bool = False, - metadata: bool = False) -> Union[Dict, MISPEvent]: + def update_event(self, event: MISPEvent, event_id: int | None = None, pythonify: bool = False, + metadata: bool = False) -> dict | MISPEvent: """Update an event on a MISP instance: https://www.misp-project.org/openapi/#tag/Events/operation/editEvent :param event: event to update @@ -441,7 +443,7 @@ class PyMISP: e.load(updated_event) return e - def delete_event(self, event: Union[MISPEvent, int, str, UUID]) -> Dict: + def delete_event(self, event: MISPEvent | int | str | UUID) -> dict: """Delete an event from a MISP instance: https://www.misp-project.org/openapi/#tag/Events/operation/deleteEvent :param event: event to delete @@ -450,7 +452,7 @@ class PyMISP: response = self._prepare_request('POST', f'events/delete/{event_id}') return self._check_json_response(response) - def publish(self, event: Union[MISPEvent, int, str, UUID], alert: bool = False) -> Dict: + def publish(self, event: MISPEvent | int | str | UUID, alert: bool = False) -> dict: """Publish the event with one single HTTP POST: https://www.misp-project.org/openapi/#tag/Events/operation/publishEvent :param event: event to publish @@ -463,7 +465,7 @@ class PyMISP: response = self._prepare_request('POST', f'events/publish/{event_id}') return self._check_json_response(response) - def unpublish(self, event: Union[MISPEvent, int, str, UUID]) -> Dict: + def unpublish(self, event: MISPEvent | int | str | UUID) -> dict: """Unpublish the event with one single HTTP POST: https://www.misp-project.org/openapi/#tag/Events/operation/unpublishEvent :param event: event to unpublish @@ -472,7 +474,7 @@ class PyMISP: response = self._prepare_request('POST', f'events/unpublish/{event_id}') return self._check_json_response(response) - def contact_event_reporter(self, event: Union[MISPEvent, int, str, UUID], message: str) -> Dict: + def contact_event_reporter(self, event: MISPEvent | int | str | UUID, message: str) -> dict: """Send a message to the reporter of an event :param event: event with reporter to contact @@ -487,8 +489,8 @@ class PyMISP: # ## BEGIN Event Report ### - def get_event_report(self, event_report: Union[MISPEventReport, int, str, UUID], - pythonify: bool = False) -> Union[Dict, MISPEventReport]: + def get_event_report(self, event_report: MISPEventReport | int | str | UUID, + pythonify: bool = False) -> dict | MISPEventReport: """Get an event report from a MISP instance :param event_report: event report to get @@ -503,8 +505,8 @@ class PyMISP: er.from_dict(**event_report_r) return er - def get_event_reports(self, event_id: Union[int, str], - pythonify: bool = False) -> Union[Dict, List[MISPEventReport]]: + def get_event_reports(self, event_id: int | str, + pythonify: bool = False) -> dict | list[MISPEventReport]: """Get event report from a MISP instance that are attached to an event ID :param event_id: event id to get the event reports for @@ -521,7 +523,7 @@ class PyMISP: to_return.append(er) return to_return - def add_event_report(self, event: Union[MISPEvent, int, str, UUID], event_report: MISPEventReport, pythonify: bool = False) -> Union[Dict, MISPEventReport]: + def add_event_report(self, event: MISPEvent | int | str | UUID, event_report: MISPEventReport, pythonify: bool = False) -> dict | MISPEventReport: """Add an event report to an existing MISP event :param event: event to extend @@ -537,7 +539,7 @@ class PyMISP: er.from_dict(**new_event_report) return er - def update_event_report(self, event_report: MISPEventReport, event_report_id: Optional[int] = None, pythonify: bool = False) -> Union[Dict, MISPEventReport]: + def update_event_report(self, event_report: MISPEventReport, event_report_id: int | None = None, pythonify: bool = False) -> dict | MISPEventReport: """Update an event report on a MISP instance :param event_report: event report to update @@ -556,7 +558,7 @@ class PyMISP: er.from_dict(**updated_event_report) return er - def delete_event_report(self, event_report: Union[MISPEventReport, int, str, UUID], hard: bool = False) -> Dict: + def delete_event_report(self, event_report: MISPEventReport | int | str | UUID, hard: bool = False) -> dict: """Delete an event report from a MISP instance :param event_report: event report to delete @@ -574,7 +576,7 @@ class PyMISP: # ## BEGIN Object ### - def get_object(self, misp_object: Union[MISPObject, int, str, UUID], pythonify: bool = False) -> Union[Dict, MISPObject]: + def get_object(self, misp_object: MISPObject | int | str | UUID, pythonify: bool = False) -> dict | MISPObject: """Get an object from the remote MISP instance: https://www.misp-project.org/openapi/#tag/Objects/operation/getObjectById :param misp_object: object to get @@ -589,7 +591,7 @@ class PyMISP: o.from_dict(**misp_object_r) return o - def object_exists(self, misp_object: Union[MISPObject, int, str, UUID]) -> bool: + def object_exists(self, misp_object: MISPObject | int | str | UUID) -> bool: """Fast check if object exists. :param misp_object: Attribute to check @@ -598,7 +600,7 @@ class PyMISP: r = self._prepare_request('HEAD', f'objects/view/{object_id}') return self._check_head_response(r) - def add_object(self, event: Union[MISPEvent, int, str, UUID], misp_object: MISPObject, pythonify: bool = False, break_on_duplicate: bool = False) -> Union[Dict, MISPObject]: + def add_object(self, event: MISPEvent | int | str | UUID, misp_object: MISPObject, pythonify: bool = False, break_on_duplicate: bool = False) -> dict | MISPObject: """Add a MISP Object to an existing MISP event: https://www.misp-project.org/openapi/#tag/Objects/operation/addObject :param event: event to extend @@ -616,7 +618,7 @@ class PyMISP: o.from_dict(**new_object) return o - def update_object(self, misp_object: MISPObject, object_id: Optional[int] = None, pythonify: bool = False) -> Union[Dict, MISPObject]: + def update_object(self, misp_object: MISPObject, object_id: int | None = None, pythonify: bool = False) -> dict | MISPObject: """Update an object on a MISP instance :param misp_object: object to update @@ -635,7 +637,7 @@ class PyMISP: o.from_dict(**updated_object) return o - def delete_object(self, misp_object: Union[MISPObject, int, str, UUID], hard: bool = False) -> Dict: + def delete_object(self, misp_object: MISPObject | int | str | UUID, hard: bool = False) -> dict: """Delete an object from a MISP instance: https://www.misp-project.org/openapi/#tag/Objects/operation/deleteObject :param misp_object: object to delete @@ -648,7 +650,7 @@ class PyMISP: r = self._prepare_request('POST', f'objects/delete/{object_id}', data=data) return self._check_json_response(r) - def add_object_reference(self, misp_object_reference: MISPObjectReference, pythonify: bool = False) -> Union[Dict, MISPObjectReference]: + def add_object_reference(self, misp_object_reference: MISPObjectReference, pythonify: bool = False) -> dict | MISPObjectReference: """Add a reference to an object :param misp_object_reference: object reference @@ -664,9 +666,9 @@ class PyMISP: def delete_object_reference( self, - object_reference: Union[MISPObjectReference, int, str, UUID], + object_reference: MISPObjectReference | int | str | UUID, hard: bool = False, - ) -> Dict: + ) -> dict: """Delete a reference to an object.""" object_reference_id = get_uuid_or_id_from_abstract_misp(object_reference) query_url = f"objectReferences/delete/{object_reference_id}" @@ -677,7 +679,7 @@ class PyMISP: # Object templates - def object_templates(self, pythonify: bool = False) -> Union[Dict, List[MISPObjectTemplate]]: + def object_templates(self, pythonify: bool = False) -> dict | list[MISPObjectTemplate]: """Get all the object templates :param pythonify: Returns a list of PyMISP Objects instead of the plain json output. Warning: it might use a lot of RAM @@ -693,7 +695,7 @@ class PyMISP: to_return.append(o) return to_return - def get_object_template(self, object_template: Union[MISPObjectTemplate, int, str, UUID], pythonify: bool = False) -> Union[Dict, MISPObjectTemplate]: + def get_object_template(self, object_template: MISPObjectTemplate | int | str | UUID, pythonify: bool = False) -> dict | MISPObjectTemplate: """Gets the full object template :param object_template: template or ID to get @@ -708,14 +710,14 @@ class PyMISP: t.from_dict(**object_template_r) return t - def get_raw_object_template(self, uuid_or_name: str) -> Dict: + def get_raw_object_template(self, uuid_or_name: str) -> dict: """Get a row template. It needs to be present on disk on the MISP instance you're connected to. The response of this method can be passed to MISPObject(, misp_objects_template_custom=) """ r = self._prepare_request('GET', f'objectTemplates/getRaw/{uuid_or_name}') return self._check_json_response(r) - def update_object_templates(self) -> Dict: + def update_object_templates(self) -> dict: """Trigger an update of the object templates""" response = self._prepare_request('POST', 'objectTemplates/update') return self._check_json_response(response) @@ -724,7 +726,7 @@ class PyMISP: # ## BEGIN Attribute ### - def attributes(self, pythonify: bool = False) -> Union[Dict, List[MISPAttribute]]: + def attributes(self, pythonify: bool = False) -> dict | list[MISPAttribute]: """Get all the attributes from the MISP instance: https://www.misp-project.org/openapi/#tag/Attributes/operation/getAttributes :param pythonify: Returns a list of PyMISP Objects instead of the plain json output. Warning: it might use a lot of RAM @@ -740,7 +742,7 @@ class PyMISP: to_return.append(a) return to_return - def get_attribute(self, attribute: Union[MISPAttribute, int, str, UUID], pythonify: bool = False) -> Union[Dict, MISPAttribute]: + def get_attribute(self, attribute: MISPAttribute | int | str | UUID, pythonify: bool = False) -> dict | MISPAttribute: """Get an attribute from a MISP instance: https://www.misp-project.org/openapi/#tag/Attributes/operation/getAttributeById :param attribute: attribute to get @@ -755,7 +757,7 @@ class PyMISP: a.from_dict(**attribute_r) return a - def attribute_exists(self, attribute: Union[MISPAttribute, int, str, UUID]) -> bool: + def attribute_exists(self, attribute: MISPAttribute | int | str | UUID) -> bool: """Fast check if attribute exists. :param attribute: Attribute to check @@ -764,7 +766,7 @@ class PyMISP: r = self._prepare_request('HEAD', f'attributes/view/{attribute_id}') return self._check_head_response(r) - def add_attribute(self, event: Union[MISPEvent, int, str, UUID], attribute: Union[MISPAttribute, Iterable], pythonify: bool = False, break_on_duplicate: bool = True) -> Union[Dict, MISPAttribute, MISPShadowAttribute]: + def add_attribute(self, event: MISPEvent | int | str | UUID, attribute: MISPAttribute | Iterable, pythonify: bool = False, break_on_duplicate: bool = True) -> dict | MISPAttribute | MISPShadowAttribute: """Add an attribute to an existing MISP event: https://www.misp-project.org/openapi/#tag/Attributes/operation/addAttribute :param event: event to extend @@ -782,7 +784,7 @@ class PyMISP: # Multiple attributes were passed at once, the handling is totally different if not (self.global_pythonify or pythonify): return new_attribute - to_return: Dict[str, List[MISPAttribute]] = {'attributes': []} + to_return: dict[str, list[MISPAttribute]] = {'attributes': []} if 'errors' in new_attribute: to_return['errors'] = new_attribute['errors'] @@ -811,7 +813,7 @@ class PyMISP: a.from_dict(**new_attribute) return a - def update_attribute(self, attribute: MISPAttribute, attribute_id: Optional[int] = None, pythonify: bool = False) -> Union[Dict, MISPAttribute, MISPShadowAttribute]: + def update_attribute(self, attribute: MISPAttribute, attribute_id: int | None = None, pythonify: bool = False) -> dict | MISPAttribute | MISPShadowAttribute: """Update an attribute on a MISP instance: https://www.misp-project.org/openapi/#tag/Attributes/operation/editAttribute :param attribute: attribute to update @@ -836,7 +838,7 @@ class PyMISP: a.from_dict(**updated_attribute) return a - def delete_attribute(self, attribute: Union[MISPAttribute, int, str, UUID], hard: bool = False) -> Dict: + def delete_attribute(self, attribute: MISPAttribute | int | str | UUID, hard: bool = False) -> dict: """Delete an attribute from a MISP instance: https://www.misp-project.org/openapi/#tag/Attributes/operation/deleteAttribute :param attribute: attribute to delete @@ -856,7 +858,7 @@ class PyMISP: return self.delete_attribute_proposal(attribute_id) return response - def restore_attribute(self, attribute: Union[MISPAttribute, int, str, UUID], pythonify: bool = False) -> Union[Dict, MISPAttribute]: + def restore_attribute(self, attribute: MISPAttribute | int | str | UUID, pythonify: bool = False) -> dict | MISPAttribute: """Restore a soft deleted attribute from a MISP instance: https://www.misp-project.org/openapi/#tag/Attributes/operation/restoreAttribute :param attribute: attribute to restore @@ -874,7 +876,7 @@ class PyMISP: # ## BEGIN Attribute Proposal ### - def attribute_proposals(self, event: Optional[Union[MISPEvent, int, str, UUID]] = None, pythonify: bool = False) -> Union[Dict, List[MISPShadowAttribute]]: + def attribute_proposals(self, event: MISPEvent | int | str | UUID | None = None, pythonify: bool = False) -> dict | list[MISPShadowAttribute]: """Get all the attribute proposals :param event: event @@ -895,7 +897,7 @@ class PyMISP: to_return.append(a) return to_return - def get_attribute_proposal(self, proposal: Union[MISPShadowAttribute, int, str, UUID], pythonify: bool = False) -> Union[Dict, MISPShadowAttribute]: + def get_attribute_proposal(self, proposal: MISPShadowAttribute | int | str | UUID, pythonify: bool = False) -> dict | MISPShadowAttribute: """Get an attribute proposal :param proposal: proposal to get @@ -912,7 +914,7 @@ class PyMISP: # NOTE: the tree following method have a very specific meaning, look at the comments - def add_attribute_proposal(self, event: Union[MISPEvent, int, str, UUID], attribute: MISPAttribute, pythonify: bool = False) -> Union[Dict, MISPShadowAttribute]: + def add_attribute_proposal(self, event: MISPEvent | int | str | UUID, attribute: MISPAttribute, pythonify: bool = False) -> dict | MISPShadowAttribute: """Propose a new attribute in an event :param event: event to receive new attribute @@ -928,7 +930,7 @@ class PyMISP: a.from_dict(**new_attribute_proposal) return a - def update_attribute_proposal(self, initial_attribute: Union[MISPAttribute, int, str, UUID], attribute: MISPAttribute, pythonify: bool = False) -> Union[Dict, MISPShadowAttribute]: + def update_attribute_proposal(self, initial_attribute: MISPAttribute | int | str | UUID, attribute: MISPAttribute, pythonify: bool = False) -> dict | MISPShadowAttribute: """Propose a change for an attribute :param initial_attribute: attribute to change @@ -944,7 +946,7 @@ class PyMISP: a.from_dict(**update_attribute_proposal) return a - def delete_attribute_proposal(self, attribute: Union[MISPAttribute, int, str, UUID]) -> Dict: + def delete_attribute_proposal(self, attribute: MISPAttribute | int | str | UUID) -> dict: """Propose the deletion of an attribute :param attribute: attribute to delete @@ -953,7 +955,7 @@ class PyMISP: response = self._prepare_request('POST', f'shadowAttributes/delete/{attribute_id}') return self._check_json_response(response) - def accept_attribute_proposal(self, proposal: Union[MISPShadowAttribute, int, str, UUID]) -> Dict: + def accept_attribute_proposal(self, proposal: MISPShadowAttribute | int | str | UUID) -> dict: """Accept a proposal. You cannot modify an existing proposal, only accept/discard :param proposal: attribute proposal to accept @@ -962,7 +964,7 @@ class PyMISP: response = self._prepare_request('POST', f'shadowAttributes/accept/{proposal_id}') return self._check_json_response(response) - def discard_attribute_proposal(self, proposal: Union[MISPShadowAttribute, int, str, UUID]) -> Dict: + def discard_attribute_proposal(self, proposal: MISPShadowAttribute | int | str | UUID) -> dict: """Discard a proposal. You cannot modify an existing proposal, only accept/discard :param proposal: attribute proposal to discard @@ -975,9 +977,9 @@ class PyMISP: # ## BEGIN Sighting ### - def sightings(self, misp_entity: Optional[AbstractMISP] = None, - org: Optional[Union[MISPOrganisation, int, str, UUID]] = None, - pythonify: bool = False) -> Union[Dict, List[MISPSighting]]: + def sightings(self, misp_entity: AbstractMISP | None = None, + org: MISPOrganisation | int | str | UUID | None = None, + pythonify: bool = False) -> dict | list[MISPSighting]: """Get the list of sightings related to a MISPEvent or a MISPAttribute (depending on type of misp_entity): https://www.misp-project.org/openapi/#tag/Sightings/operation/getSightingsByEventId :param misp_entity: MISP entity @@ -1010,8 +1012,8 @@ class PyMISP: return to_return def add_sighting(self, sighting: MISPSighting, - attribute: Optional[Union[MISPAttribute, int, str, UUID]] = None, - pythonify: bool = False) -> Union[Dict, MISPSighting]: + attribute: MISPAttribute | int | str | UUID | None = None, + pythonify: bool = False) -> dict | MISPSighting: """Add a new sighting (globally, or to a specific attribute): https://www.misp-project.org/openapi/#tag/Sightings/operation/addSighting and https://www.misp-project.org/openapi/#tag/Sightings/operation/getSightingsByEventId :param sighting: sighting to add @@ -1031,7 +1033,7 @@ class PyMISP: s.from_dict(**new_sighting) return s - def delete_sighting(self, sighting: Union[MISPSighting, int, str, UUID]) -> Dict: + def delete_sighting(self, sighting: MISPSighting | int | str | UUID) -> dict: """Delete a sighting from a MISP instance: https://www.misp-project.org/openapi/#tag/Sightings/operation/deleteSighting :param sighting: sighting to delete @@ -1044,7 +1046,7 @@ class PyMISP: # ## BEGIN Tags ### - def tags(self, pythonify: bool = False, **kw_params) -> Union[Dict, List[MISPTag]]: + def tags(self, pythonify: bool = False, **kw_params) -> dict | list[MISPTag]: """Get the list of existing tags: https://www.misp-project.org/openapi/#tag/Tags/operation/getTags :param pythonify: Returns a list of PyMISP Objects instead of the plain json output. Warning: it might use a lot of RAM @@ -1060,7 +1062,7 @@ class PyMISP: to_return.append(t) return to_return - def get_tag(self, tag: Union[MISPTag, int, str, UUID], pythonify: bool = False) -> Union[Dict, MISPTag]: + def get_tag(self, tag: MISPTag | int | str | UUID, pythonify: bool = False) -> dict | MISPTag: """Get a tag by id: https://www.misp-project.org/openapi/#tag/Tags/operation/getTagById :param tag: tag to get @@ -1075,7 +1077,7 @@ class PyMISP: t.from_dict(**tag_r) return t - def add_tag(self, tag: MISPTag, pythonify: bool = False) -> Union[Dict, MISPTag]: + def add_tag(self, tag: MISPTag, pythonify: bool = False) -> dict | MISPTag: """Add a new tag on a MISP instance: https://www.misp-project.org/openapi/#tag/Tags/operation/addTag The user calling this method needs the Tag Editor permission. It doesn't add a tag to an event, simply creates it on the MISP instance. @@ -1091,7 +1093,7 @@ class PyMISP: t.from_dict(**new_tag) return t - def enable_tag(self, tag: MISPTag, pythonify: bool = False) -> Union[Dict, MISPTag]: + def enable_tag(self, tag: MISPTag, pythonify: bool = False) -> dict | MISPTag: """Enable a tag :param tag: tag to enable @@ -1100,7 +1102,7 @@ class PyMISP: tag.hide_tag = False return self.update_tag(tag, pythonify=pythonify) - def disable_tag(self, tag: MISPTag, pythonify: bool = False) -> Union[Dict, MISPTag]: + def disable_tag(self, tag: MISPTag, pythonify: bool = False) -> dict | MISPTag: """Disable a tag :param tag: tag to disable @@ -1109,7 +1111,7 @@ class PyMISP: tag.hide_tag = True return self.update_tag(tag, pythonify=pythonify) - def update_tag(self, tag: MISPTag, tag_id: Optional[int] = None, pythonify: bool = False) -> Union[Dict, MISPTag]: + def update_tag(self, tag: MISPTag, tag_id: int | None = None, pythonify: bool = False) -> dict | MISPTag: """Edit only the provided parameters of a tag: https://www.misp-project.org/openapi/#tag/Tags/operation/editTag :param tag: tag to update @@ -1128,7 +1130,7 @@ class PyMISP: t.from_dict(**updated_tag) return t - def delete_tag(self, tag: Union[MISPTag, int, str, UUID]) -> Dict: + def delete_tag(self, tag: MISPTag | int | str | UUID) -> dict: """Delete a tag from a MISP instance: https://www.misp-project.org/openapi/#tag/Tags/operation/deleteTag :param tag: tag to delete @@ -1137,7 +1139,7 @@ class PyMISP: response = self._prepare_request('POST', f'tags/delete/{tag_id}') return self._check_json_response(response) - def search_tags(self, tagname: str, strict_tagname: bool = False, pythonify: bool = False) -> Union[Dict, List[MISPTag]]: + def search_tags(self, tagname: str, strict_tagname: bool = False, pythonify: bool = False) -> dict | list[MISPTag]: """Search for tags by name: https://www.misp-project.org/openapi/#tag/Tags/operation/searchTag :param tag_name: Name to search, use % for substrings matches. @@ -1148,7 +1150,7 @@ class PyMISP: normalized_response = self._check_json_response(response) if not (self.global_pythonify or pythonify) or 'errors' in normalized_response: return normalized_response - to_return: List[MISPTag] = [] + to_return: list[MISPTag] = [] for tag in normalized_response: t = MISPTag() t.from_dict(**tag) @@ -1159,7 +1161,7 @@ class PyMISP: # ## BEGIN Taxonomies ### - def taxonomies(self, pythonify: bool = False) -> Union[Dict, List[MISPTaxonomy]]: + def taxonomies(self, pythonify: bool = False) -> dict | list[MISPTaxonomy]: """Get all the taxonomies: https://www.misp-project.org/openapi/#tag/Taxonomies/operation/getTaxonomies :param pythonify: Returns a list of PyMISP Objects instead of the plain json output. Warning: it might use a lot of RAM @@ -1175,7 +1177,7 @@ class PyMISP: to_return.append(t) return to_return - def get_taxonomy(self, taxonomy: Union[MISPTaxonomy, int, str, UUID], pythonify: bool = False) -> Union[Dict, MISPTaxonomy]: + def get_taxonomy(self, taxonomy: MISPTaxonomy | int | str | UUID, pythonify: bool = False) -> dict | MISPTaxonomy: """Get a taxonomy by id or namespace from a MISP instance: https://www.misp-project.org/openapi/#tag/Taxonomies/operation/getTaxonomyById :param taxonomy: taxonomy to get @@ -1190,7 +1192,7 @@ class PyMISP: t.from_dict(**taxonomy_r) return t - def enable_taxonomy(self, taxonomy: Union[MISPTaxonomy, int, str, UUID]) -> Dict: + def enable_taxonomy(self, taxonomy: MISPTaxonomy | int | str | UUID) -> dict: """Enable a taxonomy: https://www.misp-project.org/openapi/#tag/Taxonomies/operation/enableTaxonomy :param taxonomy: taxonomy to enable @@ -1199,7 +1201,7 @@ class PyMISP: response = self._prepare_request('POST', f'taxonomies/enable/{taxonomy_id}') return self._check_json_response(response) - def disable_taxonomy(self, taxonomy: Union[MISPTaxonomy, int, str, UUID]) -> Dict: + def disable_taxonomy(self, taxonomy: MISPTaxonomy | int | str | UUID) -> dict: """Disable a taxonomy: https://www.misp-project.org/openapi/#tag/Taxonomies/operation/disableTaxonomy :param taxonomy: taxonomy to disable @@ -1209,7 +1211,7 @@ class PyMISP: response = self._prepare_request('POST', f'taxonomies/disable/{taxonomy_id}') return self._check_json_response(response) - def disable_taxonomy_tags(self, taxonomy: Union[MISPTaxonomy, int, str, UUID]) -> Dict: + def disable_taxonomy_tags(self, taxonomy: MISPTaxonomy | int | str | UUID) -> dict: """Disable all the tags of a taxonomy :param taxonomy: taxonomy with tags to disable @@ -1218,7 +1220,7 @@ class PyMISP: response = self._prepare_request('POST', f'taxonomies/disableTag/{taxonomy_id}') return self._check_json_response(response) - def enable_taxonomy_tags(self, taxonomy: Union[MISPTaxonomy, int, str, UUID]) -> Dict: + def enable_taxonomy_tags(self, taxonomy: MISPTaxonomy | int | str | UUID) -> dict: """Enable all the tags of a taxonomy. NOTE: this is automatically done when you call enable_taxonomy :param taxonomy: taxonomy with tags to enable @@ -1231,18 +1233,18 @@ class PyMISP: raise PyMISPError(f"The taxonomy {t.namespace} is not enabled.") elif not t['Taxonomy']['enabled']: raise PyMISPError(f"The taxonomy {t['Taxonomy']['namespace']} is not enabled.") - url = urljoin(self.root_url, 'taxonomies/addTag/{}'.format(taxonomy_id)) + url = urljoin(self.root_url, f'taxonomies/addTag/{taxonomy_id}') response = self._prepare_request('POST', url) return self._check_json_response(response) - def update_taxonomies(self) -> Dict: + def update_taxonomies(self) -> dict: """Update all the taxonomies: https://www.misp-project.org/openapi/#tag/Taxonomies/operation/updateTaxonomies""" response = self._prepare_request('POST', 'taxonomies/update') return self._check_json_response(response) - def set_taxonomy_required(self, taxonomy: Union[MISPTaxonomy, int, str], required: bool = False) -> Dict: + def set_taxonomy_required(self, taxonomy: MISPTaxonomy | int | str, required: bool = False) -> dict: taxonomy_id = get_uuid_or_id_from_abstract_misp(taxonomy) - url = urljoin(self.root_url, 'taxonomies/toggleRequired/{}'.format(taxonomy_id)) + url = urljoin(self.root_url, f'taxonomies/toggleRequired/{taxonomy_id}') payload = { "Taxonomy": { "required": required @@ -1255,7 +1257,7 @@ class PyMISP: # ## BEGIN Warninglists ### - def warninglists(self, pythonify: bool = False) -> Union[Dict, List[MISPWarninglist]]: + def warninglists(self, pythonify: bool = False) -> dict | list[MISPWarninglist]: """Get all the warninglists: https://www.misp-project.org/openapi/#tag/Warninglists/operation/getWarninglists :param pythonify: Returns a list of PyMISP Objects instead of the plain json output. Warning: it might use a lot of RAM @@ -1271,7 +1273,7 @@ class PyMISP: to_return.append(w) return to_return - def get_warninglist(self, warninglist: Union[MISPWarninglist, int, str, UUID], pythonify: bool = False) -> Union[Dict, MISPWarninglist]: + def get_warninglist(self, warninglist: MISPWarninglist | int | str | UUID, pythonify: bool = False) -> dict | MISPWarninglist: """Get a warninglist by id: https://www.misp-project.org/openapi/#tag/Warninglists/operation/getWarninglistById :param warninglist: warninglist to get @@ -1286,7 +1288,7 @@ class PyMISP: w.from_dict(**wl) return w - def toggle_warninglist(self, warninglist_id: Optional[Union[str, int, List[int]]] = None, warninglist_name: Optional[Union[str, List[str]]] = None, force_enable: bool = False) -> Dict: + def toggle_warninglist(self, warninglist_id: str | int | list[int] | None = None, warninglist_name: str | list[str] | None = None, force_enable: bool = False) -> dict: '''Toggle (enable/disable) the status of a warninglist by id: https://www.misp-project.org/openapi/#tag/Warninglists/operation/toggleEnableWarninglist :param warninglist_id: ID of the WarningList @@ -1295,7 +1297,7 @@ class PyMISP: ''' if warninglist_id is None and warninglist_name is None: raise PyMISPError('Either warninglist_id or warninglist_name is required.') - query: Dict[str, Union[List[str], List[int], bool]] = {} + query: dict[str, list[str] | list[int] | bool] = {} if warninglist_id is not None: if isinstance(warninglist_id, list): query['id'] = warninglist_id @@ -1311,7 +1313,7 @@ class PyMISP: response = self._prepare_request('POST', 'warninglists/toggleEnable', data=query) return self._check_json_response(response) - def enable_warninglist(self, warninglist: Union[MISPWarninglist, int, str, UUID]) -> Dict: + def enable_warninglist(self, warninglist: MISPWarninglist | int | str | UUID) -> dict: """Enable a warninglist :param warninglist: warninglist to enable @@ -1319,7 +1321,7 @@ class PyMISP: warninglist_id = get_uuid_or_id_from_abstract_misp(warninglist) return self.toggle_warninglist(warninglist_id=warninglist_id, force_enable=True) - def disable_warninglist(self, warninglist: Union[MISPWarninglist, int, str, UUID]) -> Dict: + def disable_warninglist(self, warninglist: MISPWarninglist | int | str | UUID) -> dict: """Disable a warninglist :param warninglist: warninglist to disable @@ -1327,7 +1329,7 @@ class PyMISP: warninglist_id = get_uuid_or_id_from_abstract_misp(warninglist) return self.toggle_warninglist(warninglist_id=warninglist_id, force_enable=False) - def values_in_warninglist(self, value: Iterable) -> Dict: + def values_in_warninglist(self, value: Iterable) -> dict: """Check if IOC values are in warninglist :param value: iterator with values to check @@ -1335,7 +1337,7 @@ class PyMISP: response = self._prepare_request('POST', 'warninglists/checkValue', data=value) return self._check_json_response(response) - def update_warninglists(self) -> Dict: + def update_warninglists(self) -> dict: """Update all the warninglists: https://www.misp-project.org/openapi/#tag/Warninglists/operation/updateWarninglists""" response = self._prepare_request('POST', 'warninglists/update') return self._check_json_response(response) @@ -1344,7 +1346,7 @@ class PyMISP: # ## BEGIN Noticelist ### - def noticelists(self, pythonify: bool = False) -> Union[Dict, List[MISPNoticelist]]: + def noticelists(self, pythonify: bool = False) -> dict | list[MISPNoticelist]: """Get all the noticelists: https://www.misp-project.org/openapi/#tag/Noticelists/operation/getNoticelists :param pythonify: Returns a list of PyMISP Objects instead of the plain json output. Warning: it might use a lot of RAM @@ -1360,7 +1362,7 @@ class PyMISP: to_return.append(n) return to_return - def get_noticelist(self, noticelist: Union[MISPNoticelist, int, str, UUID], pythonify: bool = False) -> Union[Dict, MISPNoticelist]: + def get_noticelist(self, noticelist: MISPNoticelist | int | str | UUID, pythonify: bool = False) -> dict | MISPNoticelist: """Get a noticelist by id: https://www.misp-project.org/openapi/#tag/Noticelists/operation/getNoticelistById :param notistlist: Noticelist to get @@ -1375,7 +1377,7 @@ class PyMISP: n.from_dict(**noticelist_j) return n - def enable_noticelist(self, noticelist: Union[MISPNoticelist, int, str, UUID]) -> Dict: + def enable_noticelist(self, noticelist: MISPNoticelist | int | str | UUID) -> dict: """Enable a noticelist by id: https://www.misp-project.org/openapi/#tag/Noticelists/operation/toggleEnableNoticelist :param noticelist: Noticelist to enable @@ -1386,7 +1388,7 @@ class PyMISP: response = self._prepare_request('POST', f'noticelists/enableNoticelist/{noticelist_id}/true') return self._check_json_response(response) - def disable_noticelist(self, noticelist: Union[MISPNoticelist, int, str, UUID]) -> Dict: + def disable_noticelist(self, noticelist: MISPNoticelist | int | str | UUID) -> dict: """Disable a noticelist by id :param noticelist: Noticelist to disable @@ -1397,7 +1399,7 @@ class PyMISP: response = self._prepare_request('POST', f'noticelists/enableNoticelist/{noticelist_id}') return self._check_json_response(response) - def update_noticelists(self) -> Dict: + def update_noticelists(self) -> dict: """Update all the noticelists: https://www.misp-project.org/openapi/#tag/Noticelists/operation/updateNoticelists""" response = self._prepare_request('POST', 'noticelists/update') return self._check_json_response(response) @@ -1406,7 +1408,7 @@ class PyMISP: # ## BEGIN Correlation Exclusions ### - def correlation_exclusions(self, pythonify: bool = False) -> Union[Dict, List[MISPCorrelationExclusion]]: + def correlation_exclusions(self, pythonify: bool = False) -> dict | list[MISPCorrelationExclusion]: """Get all the correlation exclusions :param pythonify: Returns a list of PyMISP Objects instead of the plain json output. Warning: it might use a lot of RAM @@ -1422,7 +1424,7 @@ class PyMISP: to_return.append(c) return to_return - def get_correlation_exclusion(self, correlation_exclusion: Union[MISPCorrelationExclusion, int, str, UUID], pythonify: bool = False) -> Union[Dict, MISPCorrelationExclusion]: + def get_correlation_exclusion(self, correlation_exclusion: MISPCorrelationExclusion | int | str | UUID, pythonify: bool = False) -> dict | MISPCorrelationExclusion: """Get a correlation exclusion by ID :param correlation_exclusion: Correlation exclusion to get @@ -1437,7 +1439,7 @@ class PyMISP: c.from_dict(**correlation_exclusion_j) return c - def add_correlation_exclusion(self, correlation_exclusion: MISPCorrelationExclusion, pythonify: bool = False) -> Union[Dict, MISPCorrelationExclusion]: + def add_correlation_exclusion(self, correlation_exclusion: MISPCorrelationExclusion, pythonify: bool = False) -> dict | MISPCorrelationExclusion: """Add a new correlation exclusion :param correlation_exclusion: correlation exclusion to add @@ -1451,7 +1453,7 @@ class PyMISP: c.from_dict(**new_correlation_exclusion) return c - def delete_correlation_exclusion(self, correlation_exclusion: Union[MISPCorrelationExclusion, int, str, UUID]) -> Dict: + def delete_correlation_exclusion(self, correlation_exclusion: MISPCorrelationExclusion | int | str | UUID) -> dict: """Delete a correlation exclusion :param correlation_exclusion: The MISPCorrelationExclusion you wish to delete from MISP @@ -1473,7 +1475,7 @@ class PyMISP: self, withCluster: bool = False, pythonify: bool = False, - ) -> Union[Dict, List[MISPGalaxy]]: + ) -> dict | list[MISPGalaxy]: """Get all the galaxies: https://www.misp-project.org/openapi/#tag/Galaxies/operation/getGalaxies :param pythonify: Returns a list of PyMISP Objects instead of the plain json output. Warning: it might use a lot of RAM @@ -1494,7 +1496,7 @@ class PyMISP: value: str, withCluster: bool = False, pythonify: bool = False, - ) -> Union[Dict, List[MISPGalaxy]]: + ) -> dict | list[MISPGalaxy]: """Text search to find a matching galaxy name, namespace, description, or uuid.""" r = self._prepare_request("POST", "galaxies", data={"value": value}) galaxies = self._check_json_response(r) @@ -1507,7 +1509,7 @@ class PyMISP: to_return.append(g) return to_return - def get_galaxy(self, galaxy: Union[MISPGalaxy, int, str, UUID], withCluster: bool = False, pythonify: bool = False) -> Union[Dict, MISPGalaxy]: + def get_galaxy(self, galaxy: MISPGalaxy | int | str | UUID, withCluster: bool = False, pythonify: bool = False) -> dict | MISPGalaxy: """Get a galaxy by id: https://www.misp-project.org/openapi/#tag/Galaxies/operation/getGalaxyById :param galaxy: galaxy to get @@ -1523,7 +1525,7 @@ class PyMISP: g.from_dict(**galaxy_j, withCluster=withCluster) return g - def search_galaxy_clusters(self, galaxy: Union[MISPGalaxy, int, str, UUID], context: str = "all", searchall: Optional[str] = None, pythonify: bool = False) -> Union[Dict, List[MISPGalaxyCluster]]: + def search_galaxy_clusters(self, galaxy: MISPGalaxy | int | str | UUID, context: str = "all", searchall: str | None = None, pythonify: bool = False) -> dict | list[MISPGalaxyCluster]: """Searches the galaxy clusters within a specific galaxy: https://www.misp-project.org/openapi/#tag/Galaxy-Clusters/operation/getGalaxyClusters and https://www.misp-project.org/openapi/#tag/Galaxy-Clusters/operation/getGalaxyClusterById :param galaxy: The MISPGalaxy you wish to search in @@ -1533,7 +1535,7 @@ class PyMISP: """ galaxy_id = get_uuid_or_id_from_abstract_misp(galaxy) - allowed_context_types: List[str] = ["all", "default", "custom", "org", "deleted"] + allowed_context_types: list[str] = ["all", "default", "custom", "org", "deleted"] if context not in allowed_context_types: raise PyMISPError(f"The context must be one of {', '.join(allowed_context_types)}") kw_params = {"context": context} @@ -1550,12 +1552,12 @@ class PyMISP: response.append(c) return response - def update_galaxies(self) -> Dict: + def update_galaxies(self) -> dict: """Update all the galaxies: https://www.misp-project.org/openapi/#tag/Galaxies/operation/updateGalaxies""" response = self._prepare_request('POST', 'galaxies/update') return self._check_json_response(response) - def get_galaxy_cluster(self, galaxy_cluster: Union[MISPGalaxyCluster, int, str, UUID], pythonify: bool = False) -> Union[Dict, MISPGalaxyCluster]: + def get_galaxy_cluster(self, galaxy_cluster: MISPGalaxyCluster | int | str | UUID, pythonify: bool = False) -> dict | MISPGalaxyCluster: """Gets a specific galaxy cluster :param galaxy_cluster: The MISPGalaxyCluster you want to get @@ -1571,7 +1573,7 @@ class PyMISP: gc.from_dict(**cluster_j) return gc - def add_galaxy_cluster(self, galaxy: Union[MISPGalaxy, str, UUID], galaxy_cluster: MISPGalaxyCluster, pythonify: bool = False) -> Union[Dict, MISPGalaxyCluster]: + def add_galaxy_cluster(self, galaxy: MISPGalaxy | str | UUID, galaxy_cluster: MISPGalaxyCluster, pythonify: bool = False) -> dict | MISPGalaxyCluster: """Add a new galaxy cluster to a MISP Galaxy: https://www.misp-project.org/openapi/#tag/Galaxy-Clusters/operation/addGalaxyCluster :param galaxy: A MISPGalaxy (or UUID) where you wish to add the galaxy cluster @@ -1591,7 +1593,7 @@ class PyMISP: gc.from_dict(**cluster_j) return gc - def update_galaxy_cluster(self, galaxy_cluster: MISPGalaxyCluster, pythonify: bool = False) -> Union[Dict, MISPGalaxyCluster]: + def update_galaxy_cluster(self, galaxy_cluster: MISPGalaxyCluster, pythonify: bool = False) -> dict | MISPGalaxyCluster: """Update a custom galaxy cluster: https://www.misp-project.org/openapi/#tag/Galaxy-Clusters/operation/editGalaxyCluster ;param galaxy_cluster: The MISPGalaxyCluster you wish to update @@ -1610,7 +1612,7 @@ class PyMISP: gc.from_dict(**cluster_j) return gc - def publish_galaxy_cluster(self, galaxy_cluster: Union[MISPGalaxyCluster, int, str, UUID]) -> Dict: + def publish_galaxy_cluster(self, galaxy_cluster: MISPGalaxyCluster | int | str | UUID) -> dict: """Publishes a galaxy cluster: https://www.misp-project.org/openapi/#tag/Galaxy-Clusters/operation/publishGalaxyCluster :param galaxy_cluster: The galaxy cluster you wish to publish @@ -1622,7 +1624,7 @@ class PyMISP: response = self._check_json_response(r) return response - def fork_galaxy_cluster(self, galaxy: Union[MISPGalaxy, int, str, UUID], galaxy_cluster: MISPGalaxyCluster, pythonify: bool = False) -> Union[Dict, MISPGalaxyCluster]: + def fork_galaxy_cluster(self, galaxy: MISPGalaxy | int | str | UUID, galaxy_cluster: MISPGalaxyCluster, pythonify: bool = False) -> dict | MISPGalaxyCluster: """Forks an existing galaxy cluster, creating a new one with matching attributes :param galaxy: The galaxy (or galaxy ID) where the cluster you want to fork resides @@ -1646,7 +1648,7 @@ class PyMISP: gc.from_dict(**cluster_j) return gc - def delete_galaxy_cluster(self, galaxy_cluster: Union[MISPGalaxyCluster, int, str, UUID], hard=False) -> Dict: + def delete_galaxy_cluster(self, galaxy_cluster: MISPGalaxyCluster | int | str | UUID, hard=False) -> dict: """Deletes a galaxy cluster from MISP: https://www.misp-project.org/openapi/#tag/Galaxy-Clusters/operation/deleteGalaxyCluster :param galaxy_cluster: The MISPGalaxyCluster you wish to delete from MISP @@ -1662,7 +1664,7 @@ class PyMISP: r = self._prepare_request('POST', f'galaxy_clusters/delete/{cluster_id}', data=data) return self._check_json_response(r) - def add_galaxy_cluster_relation(self, galaxy_cluster_relation: MISPGalaxyClusterRelation) -> Dict: + def add_galaxy_cluster_relation(self, galaxy_cluster_relation: MISPGalaxyClusterRelation) -> dict: """Add a galaxy cluster relation, cluster relation must include cluster UUIDs in both directions @@ -1672,7 +1674,7 @@ class PyMISP: cluster_rel_j = self._check_json_response(r) return cluster_rel_j - def update_galaxy_cluster_relation(self, galaxy_cluster_relation: MISPGalaxyClusterRelation) -> Dict: + def update_galaxy_cluster_relation(self, galaxy_cluster_relation: MISPGalaxyClusterRelation) -> dict: """Update a galaxy cluster relation :param galaxy_cluster_relation: The MISPGalaxyClusterRelation to update @@ -1682,7 +1684,7 @@ class PyMISP: cluster_rel_j = self._check_json_response(r) return cluster_rel_j - def delete_galaxy_cluster_relation(self, galaxy_cluster_relation: Union[MISPGalaxyClusterRelation, int, str, UUID]) -> Dict: + def delete_galaxy_cluster_relation(self, galaxy_cluster_relation: MISPGalaxyClusterRelation | int | str | UUID) -> dict: """Delete a galaxy cluster relation :param galaxy_cluster_relation: The MISPGalaxyClusterRelation to delete @@ -1696,7 +1698,7 @@ class PyMISP: # ## BEGIN Feed ### - def feeds(self, pythonify: bool = False) -> Union[Dict, List[MISPFeed]]: + def feeds(self, pythonify: bool = False) -> dict | list[MISPFeed]: """Get the list of existing feeds: https://www.misp-project.org/openapi/#tag/Feeds/operation/getFeeds :param pythonify: Returns a list of PyMISP Objects instead of the plain json output. Warning: it might use a lot of RAM @@ -1712,7 +1714,7 @@ class PyMISP: to_return.append(f) return to_return - def get_feed(self, feed: Union[MISPFeed, int, str, UUID], pythonify: bool = False) -> Union[Dict, MISPFeed]: + def get_feed(self, feed: MISPFeed | int | str | UUID, pythonify: bool = False) -> dict | MISPFeed: """Get a feed by id: https://www.misp-project.org/openapi/#tag/Feeds/operation/getFeedById :param feed: feed to get @@ -1727,7 +1729,7 @@ class PyMISP: f.from_dict(**feed_j) return f - def add_feed(self, feed: MISPFeed, pythonify: bool = False) -> Union[Dict, MISPFeed]: + def add_feed(self, feed: MISPFeed, pythonify: bool = False) -> dict | MISPFeed: """Add a new feed on a MISP instance: https://www.misp-project.org/openapi/#tag/Feeds/operation/addFeed :param feed: feed to add @@ -1742,7 +1744,7 @@ class PyMISP: f.from_dict(**new_feed) return f - def enable_feed(self, feed: Union[MISPFeed, int, str, UUID], pythonify: bool = False) -> Union[Dict, MISPFeed]: + def enable_feed(self, feed: MISPFeed | int | str | UUID, pythonify: bool = False) -> dict | MISPFeed: """Enable a feed; fetching it will create event(s): https://www.misp-project.org/openapi/#tag/Feeds/operation/enableFeed :param feed: feed to enable @@ -1757,7 +1759,7 @@ class PyMISP: f.enabled = True return self.update_feed(feed=f, pythonify=pythonify) - def disable_feed(self, feed: Union[MISPFeed, int, str, UUID], pythonify: bool = False) -> Union[Dict, MISPFeed]: + def disable_feed(self, feed: MISPFeed | int | str | UUID, pythonify: bool = False) -> dict | MISPFeed: """Disable a feed: https://www.misp-project.org/openapi/#tag/Feeds/operation/disableFeed :param feed: feed to disable @@ -1772,7 +1774,7 @@ class PyMISP: f.enabled = False return self.update_feed(feed=f, pythonify=pythonify) - def enable_feed_cache(self, feed: Union[MISPFeed, int, str, UUID], pythonify: bool = False) -> Union[Dict, MISPFeed]: + def enable_feed_cache(self, feed: MISPFeed | int | str | UUID, pythonify: bool = False) -> dict | MISPFeed: """Enable the caching of a feed :param feed: feed to enable caching @@ -1787,7 +1789,7 @@ class PyMISP: f.caching_enabled = True return self.update_feed(feed=f, pythonify=pythonify) - def disable_feed_cache(self, feed: Union[MISPFeed, int, str, UUID], pythonify: bool = False) -> Union[Dict, MISPFeed]: + def disable_feed_cache(self, feed: MISPFeed | int | str | UUID, pythonify: bool = False) -> dict | MISPFeed: """Disable the caching of a feed :param feed: feed to disable caching @@ -1802,7 +1804,7 @@ class PyMISP: f.caching_enabled = False return self.update_feed(feed=f, pythonify=pythonify) - def update_feed(self, feed: MISPFeed, feed_id: Optional[int] = None, pythonify: bool = False) -> Union[Dict, MISPFeed]: + def update_feed(self, feed: MISPFeed, feed_id: int | None = None, pythonify: bool = False) -> dict | MISPFeed: """Update a feed on a MISP instance :param feed: feed to update @@ -1822,7 +1824,7 @@ class PyMISP: f.from_dict(**updated_feed) return f - def delete_feed(self, feed: Union[MISPFeed, int, str, UUID]) -> Dict: + def delete_feed(self, feed: MISPFeed | int | str | UUID) -> dict: """Delete a feed from a MISP instance :param feed: feed to delete @@ -1831,7 +1833,7 @@ class PyMISP: response = self._prepare_request('POST', f'feeds/delete/{feed_id}') return self._check_json_response(response) - def fetch_feed(self, feed: Union[MISPFeed, int, str, UUID]) -> Dict: + def fetch_feed(self, feed: MISPFeed | int | str | UUID) -> dict: """Fetch one single feed by id: https://www.misp-project.org/openapi/#tag/Feeds/operation/fetchFromFeed :param feed: feed to fetch @@ -1840,12 +1842,12 @@ class PyMISP: response = self._prepare_request('GET', f'feeds/fetchFromFeed/{feed_id}') return self._check_json_response(response) - def cache_all_feeds(self) -> Dict: + def cache_all_feeds(self) -> dict: """ Cache all the feeds: https://www.misp-project.org/openapi/#tag/Feeds/operation/cacheFeeds""" response = self._prepare_request('GET', 'feeds/cacheFeeds/all') return self._check_json_response(response) - def cache_feed(self, feed: Union[MISPFeed, int, str, UUID]) -> Dict: + def cache_feed(self, feed: MISPFeed | int | str | UUID) -> dict: """Cache a specific feed by id: https://www.misp-project.org/openapi/#tag/Feeds/operation/cacheFeeds :param feed: feed to cache @@ -1854,22 +1856,22 @@ class PyMISP: response = self._prepare_request('GET', f'feeds/cacheFeeds/{feed_id}') return self._check_json_response(response) - def cache_freetext_feeds(self) -> Dict: + def cache_freetext_feeds(self) -> dict: """Cache all the freetext feeds""" response = self._prepare_request('GET', 'feeds/cacheFeeds/freetext') return self._check_json_response(response) - def cache_misp_feeds(self) -> Dict: + def cache_misp_feeds(self) -> dict: """Cache all the MISP feeds""" response = self._prepare_request('GET', 'feeds/cacheFeeds/misp') return self._check_json_response(response) - def compare_feeds(self) -> Dict: + def compare_feeds(self) -> dict: """Generate the comparison matrix for all the MISP feeds""" response = self._prepare_request('GET', 'feeds/compareFeeds') return self._check_json_response(response) - def load_default_feeds(self) -> Dict: + def load_default_feeds(self) -> dict: """Load all the default feeds.""" response = self._prepare_request('POST', 'feeds/loadDefaultFeeds') return self._check_json_response(response) @@ -1878,7 +1880,7 @@ class PyMISP: # ## BEGIN Server ### - def servers(self, pythonify: bool = False) -> Union[Dict, List[MISPServer]]: + def servers(self, pythonify: bool = False) -> dict | list[MISPServer]: """Get the existing servers the MISP instance can synchronise with: https://www.misp-project.org/openapi/#tag/Servers/operation/getServers :param pythonify: Returns a list of PyMISP Objects instead of the plain json output. Warning: it might use a lot of RAM @@ -1894,7 +1896,7 @@ class PyMISP: to_return.append(s) return to_return - def get_sync_config(self, pythonify: bool = False) -> Union[Dict, MISPServer]: + def get_sync_config(self, pythonify: bool = False) -> dict | MISPServer: """Get the sync server config. WARNING: This method only works if the user calling it is a sync user @@ -1908,7 +1910,7 @@ class PyMISP: s.from_dict(**server) return s - def import_server(self, server: MISPServer, pythonify: bool = False) -> Union[Dict, MISPServer]: + def import_server(self, server: MISPServer, pythonify: bool = False) -> dict | MISPServer: """Import a sync server config received from get_sync_config :param server: sync server config @@ -1922,7 +1924,7 @@ class PyMISP: s.from_dict(**server_j) return s - def add_server(self, server: MISPServer, pythonify: bool = False) -> Union[Dict, MISPServer]: + def add_server(self, server: MISPServer, pythonify: bool = False) -> dict | MISPServer: """Add a server to synchronise with: https://www.misp-project.org/openapi/#tag/Servers/operation/getServers Note: You probably want to use PyMISP.get_sync_config and PyMISP.import_server instead @@ -1937,7 +1939,7 @@ class PyMISP: s.from_dict(**server_j) return s - def update_server(self, server: MISPServer, server_id: Optional[int] = None, pythonify: bool = False) -> Union[Dict, MISPServer]: + def update_server(self, server: MISPServer, server_id: int | None = None, pythonify: bool = False) -> dict | MISPServer: """Update a server to synchronise with: https://www.misp-project.org/openapi/#tag/Servers/operation/getServers :param server: sync server config @@ -1955,7 +1957,7 @@ class PyMISP: s.from_dict(**updated_server) return s - def delete_server(self, server: Union[MISPServer, int, str, UUID]) -> Dict: + def delete_server(self, server: MISPServer | int | str | UUID) -> dict: """Delete a sync server: https://www.misp-project.org/openapi/#tag/Servers/operation/getServers :param server: sync server config @@ -1964,7 +1966,7 @@ class PyMISP: response = self._prepare_request('POST', f'servers/delete/{server_id}') return self._check_json_response(response) - def server_pull(self, server: Union[MISPServer, int, str, UUID], event: Optional[Union[MISPEvent, int, str, UUID]] = None) -> Dict: + def server_pull(self, server: MISPServer | int | str | UUID, event: MISPEvent | int | str | UUID | None = None) -> dict: """Initialize a pull from a sync server, optionally limited to one event: https://www.misp-project.org/openapi/#tag/Servers/operation/pullServer :param server: sync server config @@ -1980,7 +1982,7 @@ class PyMISP: # FIXME: can we pythonify? return self._check_json_response(response) - def server_push(self, server: Union[MISPServer, int, str, UUID], event: Optional[Union[MISPEvent, int, str, UUID]] = None) -> Dict: + def server_push(self, server: MISPServer | int | str | UUID, event: MISPEvent | int | str | UUID | None = None) -> dict: """Initialize a push to a sync server, optionally limited to one event: https://www.misp-project.org/openapi/#tag/Servers/operation/pushServer :param server: sync server config @@ -1996,7 +1998,7 @@ class PyMISP: # FIXME: can we pythonify? return self._check_json_response(response) - def test_server(self, server: Union[MISPServer, int, str, UUID]) -> Dict: + def test_server(self, server: MISPServer | int | str | UUID) -> dict: """Test if a sync link is working as expected :param server: sync server config @@ -2009,7 +2011,7 @@ class PyMISP: # ## BEGIN Sharing group ### - def sharing_groups(self, pythonify: bool = False) -> Union[Dict, List[MISPSharingGroup]]: + def sharing_groups(self, pythonify: bool = False) -> dict | list[MISPSharingGroup]: """Get the existing sharing groups: https://www.misp-project.org/openapi/#tag/Sharing-Groups/operation/getSharingGroup :param pythonify: Returns a list of PyMISP Objects instead of the plain json output. Warning: it might use a lot of RAM @@ -2025,7 +2027,7 @@ class PyMISP: to_return.append(s) return to_return - def get_sharing_group(self, sharing_group: Union[MISPSharingGroup, int, str, UUID], pythonify: bool = False) -> Union[Dict, MISPSharingGroup]: + def get_sharing_group(self, sharing_group: MISPSharingGroup | int | str | UUID, pythonify: bool = False) -> dict | MISPSharingGroup: """Get a sharing group: https://www.misp-project.org/openapi/#tag/Sharing-Groups/operation/getSharingGroupById :param sharing_group: sharing group to find @@ -2040,7 +2042,7 @@ class PyMISP: s.from_dict(**sharing_group_resp) return s - def add_sharing_group(self, sharing_group: MISPSharingGroup, pythonify: bool = False) -> Union[Dict, MISPSharingGroup]: + def add_sharing_group(self, sharing_group: MISPSharingGroup, pythonify: bool = False) -> dict | MISPSharingGroup: """Add a new sharing group: https://www.misp-project.org/openapi/#tag/Sharing-Groups/operation/addSharingGroup :param sharing_group: sharing group to add @@ -2054,7 +2056,7 @@ class PyMISP: s.from_dict(**sharing_group_j) return s - def update_sharing_group(self, sharing_group: Union[MISPSharingGroup, dict], sharing_group_id: Optional[int] = None, pythonify: bool = False) -> Union[Dict, MISPSharingGroup]: + def update_sharing_group(self, sharing_group: MISPSharingGroup | dict, sharing_group_id: int | None = None, pythonify: bool = False) -> dict | MISPSharingGroup: """Update sharing group parameters: https://www.misp-project.org/openapi/#tag/Sharing-Groups/operation/editSharingGroup :param sharing_group: MISP Sharing Group @@ -2074,7 +2076,7 @@ class PyMISP: s.from_dict(**updated_sharing_group) return s - def sharing_group_exists(self, sharing_group: Union[MISPSharingGroup, int, str, UUID]) -> bool: + def sharing_group_exists(self, sharing_group: MISPSharingGroup | int | str | UUID) -> bool: """Fast check if sharing group exists. :param sharing_group: Sharing group to check @@ -2083,7 +2085,7 @@ class PyMISP: r = self._prepare_request('HEAD', f'sharing_groups/view/{sharing_group_id}') return self._check_head_response(r) - def delete_sharing_group(self, sharing_group: Union[MISPSharingGroup, int, str, UUID]) -> Dict: + def delete_sharing_group(self, sharing_group: MISPSharingGroup | int | str | UUID) -> dict: """Delete a sharing group: https://www.misp-project.org/openapi/#tag/Sharing-Groups/operation/deleteSharingGroup :param sharing_group: sharing group to delete @@ -2092,8 +2094,8 @@ class PyMISP: response = self._prepare_request('POST', f'sharingGroups/delete/{sharing_group_id}') return self._check_json_response(response) - def add_org_to_sharing_group(self, sharing_group: Union[MISPSharingGroup, int, str, UUID], - organisation: Union[MISPOrganisation, int, str, UUID], extend: bool = False) -> Dict: + def add_org_to_sharing_group(self, sharing_group: MISPSharingGroup | int | str | UUID, + organisation: MISPOrganisation | int | str | UUID, extend: bool = False) -> dict: '''Add an organisation to a sharing group: https://www.misp-project.org/openapi/#tag/Sharing-Groups/operation/addOrganisationToSharingGroup :param sharing_group: Sharing group's local instance ID, or Sharing group's global UUID @@ -2106,8 +2108,8 @@ class PyMISP: response = self._prepare_request('POST', 'sharingGroups/addOrg', data=to_jsonify) return self._check_json_response(response) - def remove_org_from_sharing_group(self, sharing_group: Union[MISPSharingGroup, int, str, UUID], - organisation: Union[MISPOrganisation, int, str, UUID]) -> Dict: + def remove_org_from_sharing_group(self, sharing_group: MISPSharingGroup | int | str | UUID, + organisation: MISPOrganisation | int | str | UUID) -> dict: '''Remove an organisation from a sharing group: https://www.misp-project.org/openapi/#tag/Sharing-Groups/operation/removeOrganisationFromSharingGroup :param sharing_group: Sharing group's local instance ID, or Sharing group's global UUID @@ -2119,8 +2121,8 @@ class PyMISP: response = self._prepare_request('POST', 'sharingGroups/removeOrg', data=to_jsonify) return self._check_json_response(response) - def add_server_to_sharing_group(self, sharing_group: Union[MISPSharingGroup, int, str, UUID], - server: Union[MISPServer, int, str, UUID], all_orgs: bool = False) -> Dict: + def add_server_to_sharing_group(self, sharing_group: MISPSharingGroup | int | str | UUID, + server: MISPServer | int | str | UUID, all_orgs: bool = False) -> dict: '''Add a server to a sharing group: https://www.misp-project.org/openapi/#tag/Sharing-Groups/operation/addServerToSharingGroup :param sharing_group: Sharing group's local instance ID, or Sharing group's global UUID @@ -2133,8 +2135,8 @@ class PyMISP: response = self._prepare_request('POST', 'sharingGroups/addServer', data=to_jsonify) return self._check_json_response(response) - def remove_server_from_sharing_group(self, sharing_group: Union[MISPSharingGroup, int, str, UUID], - server: Union[MISPServer, int, str, UUID]) -> Dict: + def remove_server_from_sharing_group(self, sharing_group: MISPSharingGroup | int | str | UUID, + server: MISPServer | int | str | UUID) -> dict: '''Remove a server from a sharing group: https://www.misp-project.org/openapi/#tag/Sharing-Groups/operation/removeServerFromSharingGroup :param sharing_group: Sharing group's local instance ID, or Sharing group's global UUID @@ -2150,7 +2152,7 @@ class PyMISP: # ## BEGIN Organisation ### - def organisations(self, scope="local", search: Optional[str] = None, pythonify: bool = False) -> Union[Dict, List[MISPOrganisation]]: + def organisations(self, scope="local", search: str | None = None, pythonify: bool = False) -> dict | list[MISPOrganisation]: """Get all the organisations: https://www.misp-project.org/openapi/#tag/Organisations/operation/getOrganisations :param scope: scope of organizations to get @@ -2172,7 +2174,7 @@ class PyMISP: to_return.append(o) return to_return - def get_organisation(self, organisation: Union[MISPOrganisation, int, str, UUID], pythonify: bool = False) -> Union[Dict, MISPOrganisation]: + def get_organisation(self, organisation: MISPOrganisation | int | str | UUID, pythonify: bool = False) -> dict | MISPOrganisation: """Get an organisation by id: https://www.misp-project.org/openapi/#tag/Organisations/operation/getOrganisationById :param organisation: organization to get @@ -2187,7 +2189,7 @@ class PyMISP: o.from_dict(**organisation_j) return o - def organisation_exists(self, organisation: Union[MISPOrganisation, int, str, UUID]) -> bool: + def organisation_exists(self, organisation: MISPOrganisation | int | str | UUID) -> bool: """Fast check if organisation exists. :param organisation: Organisation to check @@ -2196,7 +2198,7 @@ class PyMISP: r = self._prepare_request('HEAD', f'organisations/view/{organisation_id}') return self._check_head_response(r) - def add_organisation(self, organisation: MISPOrganisation, pythonify: bool = False) -> Union[Dict, MISPOrganisation]: + def add_organisation(self, organisation: MISPOrganisation, pythonify: bool = False) -> dict | MISPOrganisation: """Add an organisation: https://www.misp-project.org/openapi/#tag/Organisations/operation/addOrganisation :param organisation: organization to add @@ -2210,7 +2212,7 @@ class PyMISP: o.from_dict(**new_organisation) return o - def update_organisation(self, organisation: MISPOrganisation, organisation_id: Optional[int] = None, pythonify: bool = False) -> Union[Dict, MISPOrganisation]: + def update_organisation(self, organisation: MISPOrganisation, organisation_id: int | None = None, pythonify: bool = False) -> dict | MISPOrganisation: """Update an organisation: https://www.misp-project.org/openapi/#tag/Organisations/operation/editOrganisation :param organisation: organization to update @@ -2229,7 +2231,7 @@ class PyMISP: o.from_dict(**organisation) return o - def delete_organisation(self, organisation: Union[MISPOrganisation, int, str, UUID]) -> Dict: + def delete_organisation(self, organisation: MISPOrganisation | int | str | UUID) -> dict: """Delete an organisation by id: https://www.misp-project.org/openapi/#tag/Organisations/operation/deleteOrganisation :param organisation: organization to delete @@ -2243,7 +2245,7 @@ class PyMISP: # ## BEGIN User ### - def users(self, search: Optional[str] = None, organisation: Optional[int] = None, pythonify: bool = False) -> Union[Dict, List[MISPUser]]: + def users(self, search: str | None = None, organisation: int | None = None, pythonify: bool = False) -> dict | list[MISPUser]: """Get all the users, or a filtered set of users: https://www.misp-project.org/openapi/#tag/Users/operation/getUsers :param search: The search to make against the list of users @@ -2267,7 +2269,7 @@ class PyMISP: to_return.append(u) return to_return - def get_user(self, user: Union[MISPUser, int, str, UUID] = 'me', pythonify: bool = False, expanded: bool = False) -> Union[Dict, MISPUser, Tuple[MISPUser, MISPRole, List[MISPUserSetting]]]: + def get_user(self, user: MISPUser | int | str | UUID = 'me', pythonify: bool = False, expanded: bool = False) -> dict | MISPUser | tuple[MISPUser, MISPRole, list[MISPUserSetting]]: """Get a user by id: https://www.misp-project.org/openapi/#tag/Users/operation/getUsers :param user: user to get; `me` means the owner of the API key doing the query @@ -2294,7 +2296,7 @@ class PyMISP: usersettings.append(us) return u, role, usersettings - def get_new_authkey(self, user: Union[MISPUser, int, str, UUID] = 'me') -> str: + def get_new_authkey(self, user: MISPUser | int | str | UUID = 'me') -> str: '''Get a new authorization key for a specific user, defaults to user doing the call: https://www.misp-project.org/openapi/#tag/AuthKeys/operation/addAuthKey :param user: The owner of the key @@ -2307,7 +2309,7 @@ class PyMISP: else: raise PyMISPUnexpectedResponse(f'Unable to get authkey: {authkey}') - def add_user(self, user: MISPUser, pythonify: bool = False) -> Union[Dict, MISPUser]: + def add_user(self, user: MISPUser, pythonify: bool = False) -> dict | MISPUser: """Add a new user: https://www.misp-project.org/openapi/#tag/Users/operation/addUser :param user: user to add @@ -2321,7 +2323,7 @@ class PyMISP: u.from_dict(**user_j) return u - def update_user(self, user: MISPUser, user_id: Optional[int] = None, pythonify: bool = False) -> Union[Dict, MISPUser]: + def update_user(self, user: MISPUser, user_id: int | None = None, pythonify: bool = False) -> dict | MISPUser: """Update a user on a MISP instance: https://www.misp-project.org/openapi/#tag/Users/operation/editUser :param user: user to update @@ -2343,7 +2345,7 @@ class PyMISP: e.from_dict(**updated_user) return e - def delete_user(self, user: Union[MISPUser, int, str, UUID]) -> Dict: + def delete_user(self, user: MISPUser | int | str | UUID) -> dict: """Delete a user by id: https://www.misp-project.org/openapi/#tag/Users/operation/deleteUser :param user: user to delete @@ -2353,7 +2355,7 @@ class PyMISP: response = self._prepare_request('POST', f'admin/users/delete/{user_id}') return self._check_json_response(response) - def change_user_password(self, new_password: str) -> Dict: + def change_user_password(self, new_password: str) -> dict: """Change the password of the curent user: :param new_password: password to set @@ -2361,7 +2363,7 @@ class PyMISP: response = self._prepare_request('POST', 'users/change_pw', data={'password': new_password}) return self._check_json_response(response) - def user_registrations(self, pythonify: bool = False) -> Union[Dict, List[MISPInbox]]: + def user_registrations(self, pythonify: bool = False) -> dict | list[MISPInbox]: """Get all the user registrations :param pythonify: Returns a list of PyMISP Objects instead of the plain json output. Warning: it might use a lot of RAM @@ -2377,9 +2379,9 @@ class PyMISP: to_return.append(i) return to_return - def accept_user_registration(self, registration: Union[MISPInbox, int, str, UUID], - organisation: Optional[Union[MISPOrganisation, int, str, UUID]] = None, - role: Optional[Union[MISPRole, int, str]] = None, + def accept_user_registration(self, registration: MISPInbox | int | str | UUID, + organisation: MISPOrganisation | int | str | UUID | None = None, + role: MISPRole | int | str | None = None, perm_sync: bool = False, perm_publish: bool = False, perm_admin: bool = False, unsafe_fallback: bool = False): """Accept a user registration @@ -2428,7 +2430,7 @@ class PyMISP: r = self._prepare_request('POST', f'users/acceptRegistrations/{registration_id}', data=to_post) return self._check_json_response(r) - def discard_user_registration(self, registration: Union[MISPInbox, int, str, UUID]): + def discard_user_registration(self, registration: MISPInbox | int | str | UUID): """Discard a user registration :param registration: the registration to discard @@ -2441,7 +2443,7 @@ class PyMISP: # ## BEGIN Role ### - def roles(self, pythonify: bool = False) -> Union[Dict, List[MISPRole]]: + def roles(self, pythonify: bool = False) -> dict | list[MISPRole]: """Get the existing roles :param pythonify: Returns a list of PyMISP Objects instead of the plain json output. Warning: it might use a lot of RAM @@ -2457,7 +2459,7 @@ class PyMISP: to_return.append(nr) return to_return - def set_default_role(self, role: Union[MISPRole, int, str, UUID]) -> Dict: + def set_default_role(self, role: MISPRole | int | str | UUID) -> dict: """Set a default role for the new user accounts :param role: the default role to set @@ -2471,12 +2473,12 @@ class PyMISP: # ## BEGIN Decaying Models ### - def update_decaying_models(self) -> Dict: + def update_decaying_models(self) -> dict: """Update all the Decaying models""" response = self._prepare_request('POST', 'decayingModel/update') return self._check_json_response(response) - def decaying_models(self, pythonify: bool = False) -> Union[Dict, List[MISPDecayingModel]]: + def decaying_models(self, pythonify: bool = False) -> dict | list[MISPDecayingModel]: """Get all the decaying models :param pythonify: Returns a list of PyMISP Objects instead of the plain json output @@ -2492,7 +2494,7 @@ class PyMISP: to_return.append(n) return to_return - def enable_decaying_model(self, decaying_model: Union[MISPDecayingModel, int, str]) -> Dict: + def enable_decaying_model(self, decaying_model: MISPDecayingModel | int | str) -> dict: """Enable a decaying Model""" if isinstance(decaying_model, MISPDecayingModel): decaying_model_id = decaying_model.id @@ -2501,7 +2503,7 @@ class PyMISP: response = self._prepare_request('POST', f'decayingModel/enable/{decaying_model_id}') return self._check_json_response(response) - def disable_decaying_model(self, decaying_model: Union[MISPDecayingModel, int, str]) -> Dict: + def disable_decaying_model(self, decaying_model: MISPDecayingModel | int | str) -> dict: """Disable a decaying Model""" if isinstance(decaying_model, MISPDecayingModel): decaying_model_id = decaying_model.id @@ -2515,53 +2517,53 @@ class PyMISP: # ## BEGIN Search methods ### def search(self, controller: str = 'events', return_format: str = 'json', - limit: Optional[int] = None, page: Optional[int] = None, - value: Optional[SearchParameterTypes] = None, - type_attribute: Optional[SearchParameterTypes] = None, - category: Optional[SearchParameterTypes] = None, - org: Optional[SearchParameterTypes] = None, - tags: Optional[SearchParameterTypes] = None, - event_tags: Optional[SearchParameterTypes] = None, - quick_filter: Optional[str] = None, quickFilter: Optional[str] = None, - date_from: Optional[Union[datetime, date, int, str, float, None]] = None, - date_to: Optional[Union[datetime, date, int, str, float, None]] = None, - eventid: Optional[SearchType] = None, - with_attachments: Optional[bool] = None, withAttachments: Optional[bool] = None, - metadata: Optional[bool] = None, - uuid: Optional[str] = None, - publish_timestamp: Optional[Union[Union[datetime, date, int, str, float, None], - Tuple[Union[datetime, date, int, str, float, None], - Union[datetime, date, int, str, float, None]] - ]] = None, - last: Optional[Union[Union[datetime, date, int, str, float, None], - Tuple[Union[datetime, date, int, str, float, None], - Union[datetime, date, int, str, float, None]] - ]] = None, - timestamp: Optional[Union[Union[datetime, date, int, str, float, None], - Tuple[Union[datetime, date, int, str, float, None], - Union[datetime, date, int, str, float, None]] - ]] = None, - published: Optional[bool] = None, - enforce_warninglist: Optional[bool] = None, enforceWarninglist: Optional[bool] = None, - to_ids: Optional[Union[ToIDSType, List[ToIDSType]]] = None, - deleted: Optional[str] = None, - include_event_uuid: Optional[bool] = None, includeEventUuid: Optional[bool] = None, - include_event_tags: Optional[bool] = None, includeEventTags: Optional[bool] = None, - event_timestamp: Optional[Union[datetime, date, int, str, float, None]] = None, - sg_reference_only: Optional[bool] = None, - eventinfo: Optional[str] = None, - searchall: Optional[bool] = None, - requested_attributes: Optional[str] = None, - include_context: Optional[bool] = None, includeContext: Optional[bool] = None, - headerless: Optional[bool] = None, - include_sightings: Optional[bool] = None, includeSightings: Optional[bool] = None, - include_correlations: Optional[bool] = None, includeCorrelations: Optional[bool] = None, - include_decay_score: Optional[bool] = None, includeDecayScore: Optional[bool] = None, - object_name: Optional[str] = None, - exclude_decayed: Optional[bool] = None, - sharinggroup: Optional[Union[int, List[int]]] = None, - pythonify: Optional[bool] = False, - **kwargs) -> Union[Dict, str, List[Union[MISPEvent, MISPAttribute, MISPObject]]]: + limit: int | None = None, page: int | None = None, + value: SearchParameterTypes | None = None, + type_attribute: SearchParameterTypes | None = None, + category: SearchParameterTypes | None = None, + org: SearchParameterTypes | None = None, + tags: SearchParameterTypes | None = None, + event_tags: SearchParameterTypes | None = None, + quick_filter: str | None = None, quickFilter: str | None = None, + date_from: datetime | date | int | str | float | None | None = None, + date_to: datetime | date | int | str | float | None | None = None, + eventid: SearchType | None = None, + with_attachments: bool | None = None, withAttachments: bool | None = None, + metadata: bool | None = None, + uuid: str | None = None, + publish_timestamp: None | (datetime | date | int | str | float | None + | tuple[datetime | date | int | str | float | None, + datetime | date | int | str | float | None] + ) = None, + last: None | (datetime | date | int | str | float | None + | tuple[datetime | date | int | str | float | None, + datetime | date | int | str | float | None] + ) = None, + timestamp: None | (datetime | date | int | str | float | None + | tuple[datetime | date | int | str | float | None, + datetime | date | int | str | float | None] + ) = None, + published: bool | None = None, + enforce_warninglist: bool | None = None, enforceWarninglist: bool | None = None, + to_ids: ToIDSType | list[ToIDSType] | None = None, + deleted: str | None = None, + include_event_uuid: bool | None = None, includeEventUuid: bool | None = None, + include_event_tags: bool | None = None, includeEventTags: bool | None = None, + event_timestamp: datetime | date | int | str | float | None | None = None, + sg_reference_only: bool | None = None, + eventinfo: str | None = None, + searchall: bool | None = None, + requested_attributes: str | None = None, + include_context: bool | None = None, includeContext: bool | None = None, + headerless: bool | None = None, + include_sightings: bool | None = None, includeSightings: bool | None = None, + include_correlations: bool | None = None, includeCorrelations: bool | None = None, + include_decay_score: bool | None = None, includeDecayScore: bool | None = None, + object_name: str | None = None, + exclude_decayed: bool | None = None, + sharinggroup: int | list[int] | None = None, + pythonify: bool | None = False, + **kwargs) -> dict | str | list[MISPEvent | MISPAttribute | MISPObject]: '''Search in the MISP instance :param controller: Controller to search on, it can be `events`, `objects`, `attributes`. The response will either be a list of events, objects, or attributes. @@ -2734,7 +2736,7 @@ class PyMISP: if return_format == 'json' and self.global_pythonify or pythonify: # The response is in json, we can convert it to a list of pythonic MISP objects - to_return: List[Union[MISPEvent, MISPAttribute, MISPObject]] = [] + to_return: list[MISPEvent | MISPAttribute | MISPObject] = [] if controller == 'events': for e in normalized_response: me = MISPEvent() @@ -2778,35 +2780,35 @@ class PyMISP: return normalized_response def search_index(self, - all: Optional[str] = None, - attribute: Optional[str] = None, - email: Optional[str] = None, - published: Optional[bool] = None, - hasproposal: Optional[bool] = None, - eventid: Optional[SearchType] = None, - tags: Optional[SearchParameterTypes] = None, - date_from: Optional[Union[datetime, date, int, str, float, None]] = None, - date_to: Optional[Union[datetime, date, int, str, float, None]] = None, - eventinfo: Optional[str] = None, - threatlevel: Optional[List[SearchType]] = None, - distribution: Optional[List[SearchType]] = None, - analysis: Optional[List[SearchType]] = None, - org: Optional[SearchParameterTypes] = None, - timestamp: Optional[Union[Union[datetime, date, int, str, float, None], - Tuple[Union[datetime, date, int, str, float, None], - Union[datetime, date, int, str, float, None]] - ]] = None, - publish_timestamp: Optional[Union[Union[datetime, date, int, str, float, None], - Tuple[Union[datetime, date, int, str, float, None], - Union[datetime, date, int, str, float, None]] - ]] = None, - sharinggroup: Optional[List[SearchType]] = None, - minimal: Optional[bool] = None, - sort: Optional[str] = None, - desc: Optional[bool] = None, - limit: Optional[int] = None, - page: Optional[int] = None, - pythonify: Optional[bool] = None) -> Union[Dict, List[MISPEvent]]: + all: str | None = None, + attribute: str | None = None, + email: str | None = None, + published: bool | None = None, + hasproposal: bool | None = None, + eventid: SearchType | None = None, + tags: SearchParameterTypes | None = None, + date_from: datetime | date | int | str | float | None | None = None, + date_to: datetime | date | int | str | float | None | None = None, + eventinfo: str | None = None, + threatlevel: list[SearchType] | None = None, + distribution: list[SearchType] | None = None, + analysis: list[SearchType] | None = None, + org: SearchParameterTypes | None = None, + timestamp: None | (datetime | date | int | str | float | None + | tuple[datetime | date | int | str | float | None, + datetime | date | int | str | float | None] + ) = None, + publish_timestamp: None | (datetime | date | int | str | float | None + | tuple[datetime | date | int | str | float | None, + datetime | date | int | str | float | None] + ) = None, + sharinggroup: list[SearchType] | None = None, + minimal: bool | None = None, + sort: str | None = None, + desc: bool | None = None, + limit: int | None = None, + page: int | None = None, + pythonify: bool | None = None) -> dict | list[MISPEvent]: """Search event metadata shown on the event index page. Using ! in front of a value means NOT, except for parameters date_from, date_to and timestamp which cannot be negated. Criteria are AND-ed together; values in lists are OR-ed together. Return matching events @@ -2874,25 +2876,25 @@ class PyMISP: to_return.append(me) return to_return - def search_sightings(self, context: Optional[str] = None, - context_id: Optional[SearchType] = None, - type_sighting: Optional[str] = None, - date_from: Optional[Union[datetime, date, int, str, float, None]] = None, - date_to: Optional[Union[datetime, date, int, str, float, None]] = None, - publish_timestamp: Optional[Union[Union[datetime, date, int, str, float, None], - Tuple[Union[datetime, date, int, str, float, None], - Union[datetime, date, int, str, float, None]] - ]] = None, - last: Optional[Union[Union[datetime, date, int, str, float, None], - Tuple[Union[datetime, date, int, str, float, None], - Union[datetime, date, int, str, float, None]] - ]] = None, - org: Optional[SearchType] = None, - source: Optional[str] = None, - include_attribute: Optional[bool] = None, - include_event_meta: Optional[bool] = None, - pythonify: Optional[bool] = False - ) -> Union[Dict, List[Dict[str, Union[MISPEvent, MISPAttribute, MISPSighting]]]]: + def search_sightings(self, context: str | None = None, + context_id: SearchType | None = None, + type_sighting: str | None = None, + date_from: datetime | date | int | str | float | None | None = None, + date_to: datetime | date | int | str | float | None | None = None, + publish_timestamp: None | (datetime | date | int | str | float | None + | tuple[datetime | date | int | str | float | None, + datetime | date | int | str | float | None] + ) = None, + last: None | (datetime | date | int | str | float | None + | tuple[datetime | date | int | str | float | None, + datetime | date | int | str | float | None] + ) = None, + org: SearchType | None = None, + source: str | None = None, + include_attribute: bool | None = None, + include_event_meta: bool | None = None, + pythonify: bool | None = False + ) -> dict | list[dict[str, MISPEvent | MISPAttribute | MISPSighting]]: '''Search sightings :param context: The context of the search. Can be either "attribute", "event", or nothing (will then match on events and attributes). @@ -2918,7 +2920,7 @@ class PyMISP: [ ... ] >>> misp.search_sightings(context='event', context_id=17, include_event_meta=True, org=2) # return list of sighting for event 17 filtered with org id 2 ''' - query: Dict[str, Any] = {'returnFormat': 'json'} + query: dict[str, Any] = {'returnFormat': 'json'} if context is not None: if context not in ['attribute', 'event']: raise ValueError('context has to be in {}'.format(', '.join(['attribute', 'event']))) @@ -2946,7 +2948,7 @@ class PyMISP: if self.global_pythonify or pythonify: to_return = [] for s in normalized_response: - entries: Dict[str, Union[MISPEvent, MISPAttribute, MISPSighting]] = {} + entries: dict[str, MISPEvent | MISPAttribute | MISPSighting] = {} s_data = s['Sighting'] if include_event_meta: e = s_data.pop('Event') @@ -2965,13 +2967,13 @@ class PyMISP: return to_return return normalized_response - def search_logs(self, limit: Optional[int] = None, page: Optional[int] = None, - log_id: Optional[int] = None, title: Optional[str] = None, - created: Optional[Union[datetime, date, int, str, float, None]] = None, model: Optional[str] = None, - action: Optional[str] = None, user_id: Optional[int] = None, - change: Optional[str] = None, email: Optional[str] = None, - org: Optional[str] = None, description: Optional[str] = None, - ip: Optional[str] = None, pythonify: Optional[bool] = False) -> Union[Dict, List[MISPLog]]: + def search_logs(self, limit: int | None = None, page: int | None = None, + log_id: int | None = None, title: str | None = None, + created: datetime | date | int | str | float | None | None = None, model: str | None = None, + action: str | None = None, user_id: int | None = None, + change: str | None = None, email: str | None = None, + org: str | None = None, description: str | None = None, + ip: str | None = None, pythonify: bool | None = False) -> dict | list[MISPLog]: '''Search in logs Note: to run substring queries simply append/prepend/encapsulate the search term with % @@ -3011,7 +3013,7 @@ class PyMISP: to_return.append(ml) return to_return - def search_feeds(self, value: Optional[SearchParameterTypes] = None, pythonify: Optional[bool] = False) -> Union[Dict, List[MISPFeed]]: + def search_feeds(self, value: SearchParameterTypes | None = None, pythonify: bool | None = False) -> dict | list[MISPFeed]: '''Search in the feeds cached on the servers''' response = self._prepare_request('POST', 'feeds/searchCaches', data={'value': value}) normalized_response = self._check_json_response(response) @@ -3028,7 +3030,7 @@ class PyMISP: # ## BEGIN Communities ### - def communities(self, pythonify: bool = False) -> Union[Dict, List[MISPCommunity]]: + def communities(self, pythonify: bool = False) -> dict | list[MISPCommunity]: """Get all the communities :param pythonify: Returns a list of PyMISP Objects instead of the plain json output. Warning: it might use a lot of RAM @@ -3044,7 +3046,7 @@ class PyMISP: to_return.append(c) return to_return - def get_community(self, community: Union[MISPCommunity, int, str, UUID], pythonify: bool = False) -> Union[Dict, MISPCommunity]: + def get_community(self, community: MISPCommunity | int | str | UUID, pythonify: bool = False) -> dict | MISPCommunity: """Get a community by id from a MISP instance :param community: community to get @@ -3059,15 +3061,15 @@ class PyMISP: c.from_dict(**community_j) return c - def request_community_access(self, community: Union[MISPCommunity, int, str, UUID], - requestor_email_address: Optional[str] = None, - requestor_gpg_key: Optional[str] = None, - requestor_organisation_name: Optional[str] = None, - requestor_organisation_uuid: Optional[str] = None, - requestor_organisation_description: Optional[str] = None, - message: Optional[str] = None, sync: bool = False, + def request_community_access(self, community: MISPCommunity | int | str | UUID, + requestor_email_address: str | None = None, + requestor_gpg_key: str | None = None, + requestor_organisation_name: str | None = None, + requestor_organisation_uuid: str | None = None, + requestor_organisation_description: str | None = None, + message: str | None = None, sync: bool = False, anonymise_requestor_server: bool = False, - mock: bool = False) -> Dict: + mock: bool = False) -> dict: """Request the access to a community :param community: community to request access @@ -3095,7 +3097,7 @@ class PyMISP: # ## BEGIN Event Delegation ### - def event_delegations(self, pythonify: bool = False) -> Union[Dict, List[MISPEventDelegation]]: + def event_delegations(self, pythonify: bool = False) -> dict | list[MISPEventDelegation]: """Get all the event delegations :param pythonify: Returns a list of PyMISP Objects instead of the plain json output. Warning: it might use a lot of RAM @@ -3111,7 +3113,7 @@ class PyMISP: to_return.append(d) return to_return - def accept_event_delegation(self, delegation: Union[MISPEventDelegation, int, str], pythonify: bool = False) -> Dict: + def accept_event_delegation(self, delegation: MISPEventDelegation | int | str, pythonify: bool = False) -> dict: """Accept the delegation of an event :param delegation: event delegation to accept @@ -3121,7 +3123,7 @@ class PyMISP: r = self._prepare_request('POST', f'eventDelegations/acceptDelegation/{delegation_id}') return self._check_json_response(r) - def discard_event_delegation(self, delegation: Union[MISPEventDelegation, int, str], pythonify: bool = False) -> Dict: + def discard_event_delegation(self, delegation: MISPEventDelegation | int | str, pythonify: bool = False) -> dict: """Discard the delegation of an event :param delegation: event delegation to discard @@ -3131,10 +3133,10 @@ class PyMISP: r = self._prepare_request('POST', f'eventDelegations/deleteDelegation/{delegation_id}') return self._check_json_response(r) - def delegate_event(self, event: Optional[Union[MISPEvent, int, str, UUID]] = None, - organisation: Optional[Union[MISPOrganisation, int, str, UUID]] = None, - event_delegation: Optional[MISPEventDelegation] = None, - distribution: int = -1, message: str = '', pythonify: bool = False) -> Union[Dict, MISPEventDelegation]: + def delegate_event(self, event: MISPEvent | int | str | UUID | None = None, + organisation: MISPOrganisation | int | str | UUID | None = None, + event_delegation: MISPEventDelegation | None = None, + distribution: int = -1, message: str = '', pythonify: bool = False) -> dict | MISPEventDelegation: """Delegate an event. Either event and organisation OR event_delegation are required :param event: event to delegate @@ -3164,7 +3166,7 @@ class PyMISP: # ## BEGIN Others ### - def push_event_to_ZMQ(self, event: Union[MISPEvent, int, str, UUID]) -> Dict: + def push_event_to_ZMQ(self, event: MISPEvent | int | str | UUID) -> dict: """Force push an event by id on ZMQ :param event: the event to push @@ -3173,7 +3175,7 @@ class PyMISP: response = self._prepare_request('POST', f'events/pushEventToZMQ/{event_id}.json') return self._check_json_response(response) - def direct_call(self, url: str, data: Optional[Dict] = None, params: Mapping = {}, kw_params: Mapping = {}) -> Any: + def direct_call(self, url: str, data: dict | None = None, params: Mapping = {}, kw_params: Mapping = {}) -> Any: """Very lightweight call that posts a data blob (python dictionary or json string) on the URL :param url: URL to post to @@ -3187,8 +3189,8 @@ class PyMISP: response = self._prepare_request('POST', url, data=data, params=params, kw_params=kw_params) return self._check_response(response, lenient_response_type=True) - def freetext(self, event: Union[MISPEvent, int, str, UUID], string: str, adhereToWarninglists: Union[bool, str] = False, - distribution: Optional[int] = None, returnMetaAttributes: bool = False, pythonify: bool = False, **kwargs) -> Union[Dict, List[MISPAttribute]]: + def freetext(self, event: MISPEvent | int | str | UUID, string: str, adhereToWarninglists: bool | str = False, + distribution: int | None = None, returnMetaAttributes: bool = False, pythonify: bool = False, **kwargs) -> dict | list[MISPAttribute]: """Pass a text to the freetext importer :param event: event @@ -3201,7 +3203,7 @@ class PyMISP: """ event_id = get_uuid_or_id_from_abstract_misp(event) - query: Dict[str, Any] = {"value": string} + query: dict[str, Any] = {"value": string} wl_params = [False, True, 'soft'] if adhereToWarninglists in wl_params: query['adhereToWarninglists'] = adhereToWarninglists @@ -3222,14 +3224,14 @@ class PyMISP: to_return.append(a) return to_return - def upload_stix(self, path: Optional[Union[str, Path, BytesIO, StringIO]] = None, data: Optional[Union[str, bytes]] = None, version: str = '2'): + def upload_stix(self, path: str | Path | BytesIO | StringIO | None = None, data: str | bytes | None = None, version: str = '2'): """Upload a STIX file to MISP. :param path: Path to the STIX on the disk (can be a path-like object, or a pseudofile) :param data: stix object :param version: Can be 1 or 2 """ - to_post: Union[str, bytes] + to_post: str | bytes if path is not None: if isinstance(path, (str, Path)): with open(path, 'rb') as f: @@ -3243,17 +3245,17 @@ class PyMISP: if str(version) == '1': url = urljoin(self.root_url, 'events/upload_stix') - response = self._prepare_request('POST', url, data=to_post, output_type='xml', content_type='xml') # type: ignore + response = self._prepare_request('POST', url, data=to_post, output_type='xml', content_type='xml') else: url = urljoin(self.root_url, 'events/upload_stix/2') - response = self._prepare_request('POST', url, data=to_post) # type: ignore + response = self._prepare_request('POST', url, data=to_post) return response # ## END Others ### # ## BEGIN Statistics ### - def attributes_statistics(self, context: str = 'type', percentage: bool = False) -> Dict: + def attributes_statistics(self, context: str = 'type', percentage: bool = False) -> dict: """Get attribute statistics from the MISP instance :param context: "type" or "category" @@ -3269,7 +3271,7 @@ class PyMISP: response = self._prepare_request('GET', path) return self._check_json_response(response) - def tags_statistics(self, percentage: bool = False, name_sort: bool = False) -> Dict: + def tags_statistics(self, percentage: bool = False, name_sort: bool = False) -> dict: """Get tag statistics from the MISP instance :param percentage: get percentages @@ -3288,7 +3290,7 @@ class PyMISP: response = self._prepare_request('GET', f'tags/tagStatistics/{p}/{ns}') return self._check_json_response(response) - def users_statistics(self, context: str = 'data') -> Dict: + def users_statistics(self, context: str = 'data') -> dict: """Get user statistics from the MISP instance :param context: one of 'data', 'orgs', 'users', 'tags', 'attributehistogram', 'sightings', 'galaxyMatrix' @@ -3303,7 +3305,7 @@ class PyMISP: # ## BEGIN User Settings ### - def user_settings(self, pythonify: bool = False) -> Union[Dict, List[MISPUserSetting]]: + def user_settings(self, pythonify: bool = False) -> dict | list[MISPUserSetting]: """Get all the user settings: https://www.misp-project.org/openapi/#tag/UserSettings/operation/getUserSettings :param pythonify: Returns a list of PyMISP Objects instead of the plain json output. Warning: it might use a lot of RAM @@ -3319,15 +3321,15 @@ class PyMISP: to_return.append(u) return to_return - def get_user_setting(self, user_setting: str, user: Optional[Union[MISPUser, int, str, UUID]] = None, - pythonify: bool = False) -> Union[Dict, MISPUserSetting]: + def get_user_setting(self, user_setting: str, user: MISPUser | int | str | UUID | None = None, + pythonify: bool = False) -> dict | MISPUserSetting: """Get a user setting: https://www.misp-project.org/openapi/#tag/UserSettings/operation/getUserSettingById :param user_setting: name of user setting :param user: user :param pythonify: Returns a PyMISP Object instead of the plain json output """ - query: Dict[str, Any] = {'setting': user_setting} + query: dict[str, Any] = {'setting': user_setting} if user: query['user_id'] = get_uuid_or_id_from_abstract_misp(user) response = self._prepare_request('POST', 'userSettings/getSetting', data=query) @@ -3338,8 +3340,8 @@ class PyMISP: u.from_dict(**user_setting_j) return u - def set_user_setting(self, user_setting: str, value: Union[str, dict], user: Optional[Union[MISPUser, int, str, UUID]] = None, - pythonify: bool = False) -> Union[Dict, MISPUserSetting]: + def set_user_setting(self, user_setting: str, value: str | dict, user: MISPUser | int | str | UUID | None = None, + pythonify: bool = False) -> dict | MISPUserSetting: """Set a user setting: https://www.misp-project.org/openapi/#tag/UserSettings/operation/setUserSetting :param user_setting: name of user setting @@ -3347,7 +3349,7 @@ class PyMISP: :param user: user :param pythonify: Returns a PyMISP Object instead of the plain json output """ - query: Dict[str, Any] = {'setting': user_setting} + query: dict[str, Any] = {'setting': user_setting} if isinstance(value, dict): value = dumps(value).decode("utf-8") if HAS_ORJSON else dumps(value) query['value'] = value @@ -3361,13 +3363,13 @@ class PyMISP: u.from_dict(**user_setting_j) return u - def delete_user_setting(self, user_setting: str, user: Optional[Union[MISPUser, int, str, UUID]] = None) -> Dict: + def delete_user_setting(self, user_setting: str, user: MISPUser | int | str | UUID | None = None) -> dict: """Delete a user setting: https://www.misp-project.org/openapi/#tag/UserSettings/operation/deleteUserSettingById :param user_setting: name of user setting :param user: user """ - query: Dict[str, Any] = {'setting': user_setting} + query: dict[str, Any] = {'setting': user_setting} if user: query['user_id'] = get_uuid_or_id_from_abstract_misp(user) response = self._prepare_request('POST', 'userSettings/delete', data=query) @@ -3377,7 +3379,7 @@ class PyMISP: # ## BEGIN Blocklists ### - def event_blocklists(self, pythonify: bool = False) -> Union[Dict, List[MISPEventBlocklist]]: + def event_blocklists(self, pythonify: bool = False) -> dict | list[MISPEventBlocklist]: """Get all the blocklisted events :param pythonify: Returns a list of PyMISP Objects instead of the plain json output. Warning: it might use a lot of RAM @@ -3393,7 +3395,7 @@ class PyMISP: to_return.append(ebl) return to_return - def organisation_blocklists(self, pythonify: bool = False) -> Union[Dict, List[MISPOrganisationBlocklist]]: + def organisation_blocklists(self, pythonify: bool = False) -> dict | list[MISPOrganisationBlocklist]: """Get all the blocklisted organisations :param pythonify: Returns a list of PyMISP Objects instead of the plain json output. Warning: it might use a lot of RAM @@ -3409,7 +3411,7 @@ class PyMISP: to_return.append(obl) return to_return - def _add_entries_to_blocklist(self, blocklist_type: str, uuids: Union[str, List[str]], **kwargs) -> Dict: + def _add_entries_to_blocklist(self, blocklist_type: str, uuids: str | list[str], **kwargs) -> dict: if blocklist_type == 'event': url = 'eventBlocklists/add' elif blocklist_type == 'organisation': @@ -3424,8 +3426,8 @@ class PyMISP: r = self._prepare_request('POST', url, data=data) return self._check_json_response(r) - def add_event_blocklist(self, uuids: Union[str, List[str]], comment: Optional[str] = None, - event_info: Optional[str] = None, event_orgc: Optional[str] = None) -> Dict: + def add_event_blocklist(self, uuids: str | list[str], comment: str | None = None, + event_info: str | None = None, event_orgc: str | None = None) -> dict: """Add a new event in the blocklist :param uuids: UUIDs @@ -3435,8 +3437,8 @@ class PyMISP: """ return self._add_entries_to_blocklist('event', uuids=uuids, comment=comment, event_info=event_info, event_orgc=event_orgc) - def add_organisation_blocklist(self, uuids: Union[str, List[str]], comment: Optional[str] = None, - org_name: Optional[str] = None) -> Dict: + def add_organisation_blocklist(self, uuids: str | list[str], comment: str | None = None, + org_name: str | None = None) -> dict: """Add a new organisation in the blocklist :param uuids: UUIDs @@ -3445,7 +3447,7 @@ class PyMISP: """ return self._add_entries_to_blocklist('organisation', uuids=uuids, comment=comment, org_name=org_name) - def _update_entries_in_blocklist(self, blocklist_type: str, uuid, **kwargs) -> Dict: + def _update_entries_in_blocklist(self, blocklist_type: str, uuid, **kwargs) -> dict: if blocklist_type == 'event': url = f'eventBlocklists/edit/{uuid}' elif blocklist_type == 'organisation': @@ -3456,7 +3458,7 @@ class PyMISP: r = self._prepare_request('POST', url, data=data) return self._check_json_response(r) - def update_event_blocklist(self, event_blocklist: MISPEventBlocklist, event_blocklist_id: Optional[Union[int, str, UUID]] = None, pythonify: bool = False) -> Union[Dict, MISPEventBlocklist]: + def update_event_blocklist(self, event_blocklist: MISPEventBlocklist, event_blocklist_id: int | str | UUID | None = None, pythonify: bool = False) -> dict | MISPEventBlocklist: """Update an event in the blocklist :param event_blocklist: event block list @@ -3474,7 +3476,7 @@ class PyMISP: e.from_dict(**updated_event_blocklist) return e - def update_organisation_blocklist(self, organisation_blocklist: MISPOrganisationBlocklist, organisation_blocklist_id: Optional[Union[int, str, UUID]] = None, pythonify: bool = False) -> Union[Dict, MISPOrganisationBlocklist]: + def update_organisation_blocklist(self, organisation_blocklist: MISPOrganisationBlocklist, organisation_blocklist_id: int | str | UUID | None = None, pythonify: bool = False) -> dict | MISPOrganisationBlocklist: """Update an organisation in the blocklist :param organisation_blocklist: organization block list @@ -3492,7 +3494,7 @@ class PyMISP: o.from_dict(**updated_organisation_blocklist) return o - def delete_event_blocklist(self, event_blocklist: Union[MISPEventBlocklist, str, UUID]) -> Dict: + def delete_event_blocklist(self, event_blocklist: MISPEventBlocklist | str | UUID) -> dict: """Delete a blocklisted event by id :param event_blocklist: event block list to delete @@ -3501,7 +3503,7 @@ class PyMISP: response = self._prepare_request('POST', f'eventBlocklists/delete/{event_blocklist_id}') return self._check_json_response(response) - def delete_organisation_blocklist(self, organisation_blocklist: Union[MISPOrganisationBlocklist, str, UUID]) -> Dict: + def delete_organisation_blocklist(self, organisation_blocklist: MISPOrganisationBlocklist | str | UUID) -> dict: """Delete a blocklisted organisation by id :param organisation_blocklist: organization block list to delete @@ -3514,7 +3516,7 @@ class PyMISP: # ## BEGIN Global helpers ### - def change_sharing_group_on_entity(self, misp_entity: Union[MISPEvent, MISPAttribute, MISPObject], sharing_group_id, pythonify: bool = False) -> Union[Dict, MISPEvent, MISPObject, MISPAttribute, MISPShadowAttribute]: + def change_sharing_group_on_entity(self, misp_entity: MISPEvent | MISPAttribute | MISPObject, sharing_group_id, pythonify: bool = False) -> dict | MISPEvent | MISPObject | MISPAttribute | MISPShadowAttribute: """Change the sharing group of an event, an attribute, or an object :param misp_entity: entity to change @@ -3536,8 +3538,8 @@ class PyMISP: raise PyMISPError('The misp_entity must be MISPEvent, MISPObject or MISPAttribute') - def tag(self, misp_entity: Union[AbstractMISP, str, dict], tag: Union[MISPTag, str], - local: bool = False, relationship_type: Optional[str] = None) -> Dict: + def tag(self, misp_entity: AbstractMISP | str | dict, tag: MISPTag | str, + local: bool = False, relationship_type: str | None = None) -> dict: """Tag an event or an attribute. :param misp_entity: a MISPEvent, a MISP Attribute, or a UUID @@ -3556,7 +3558,7 @@ class PyMISP: response = self._prepare_request('POST', 'tags/attachTagToObject', data=to_post) return self._check_json_response(response) - def untag(self, misp_entity: Union[AbstractMISP, str, dict], tag: Union[MISPTag, str]) -> Dict: + def untag(self, misp_entity: AbstractMISP | str | dict, tag: MISPTag | str) -> dict: """Untag an event or an attribute :param misp_entity: misp_entity can be a UUID @@ -3571,9 +3573,9 @@ class PyMISP: response = self._prepare_request('POST', 'tags/removeTagFromObject', data=to_post) return self._check_json_response(response) - def build_complex_query(self, or_parameters: Optional[List[SearchType]] = None, - and_parameters: Optional[List[SearchType]] = None, - not_parameters: Optional[List[SearchType]] = None) -> Dict[str, List[SearchType]]: + def build_complex_query(self, or_parameters: list[SearchType] | None = None, + and_parameters: list[SearchType] | None = None, + not_parameters: list[SearchType] | None = None) -> dict[str, list[SearchType]]: '''Build a complex search query. MISP expects a dictionary with AND, OR and NOT keys.''' to_return = {} if and_parameters: @@ -3619,7 +3621,7 @@ class PyMISP: with open(__file__) as f: content = f.read() - not_implemented_paths: List[str] = [] + not_implemented_paths: list[str] = [] for path in paths: if path not in content: not_implemented_paths.append(path) @@ -3628,7 +3630,7 @@ class PyMISP: # ## Internal methods ### - def _old_misp(self, minimal_version_required: tuple, removal_date: Union[str, date, datetime], method: Optional[str] = None, message: Optional[str] = None) -> bool: + def _old_misp(self, minimal_version_required: tuple, removal_date: str | date | datetime, method: str | None = None, message: str | None = None) -> bool: if self._misp_version >= minimal_version_required: return False if isinstance(removal_date, (datetime, date)): @@ -3639,13 +3641,13 @@ class PyMISP: warnings.warn(to_print, DeprecationWarning) return True - def _make_misp_bool(self, parameter: Optional[Union[bool, str]] = None) -> int: + def _make_misp_bool(self, parameter: bool | str | None = None) -> int: '''MISP wants 0 or 1 for bool, so we avoid True/False '0', '1' ''' if parameter is None: return 0 return 1 if int(parameter) else 0 - def _make_timestamp(self, value: Union[datetime, date, int, str, float, None]) -> Union[str, int, float, None]: + def _make_timestamp(self, value: datetime | date | int | str | float | None) -> str | int | float | None: '''Catch-all method to normalize anything that can be converted to a timestamp''' if not value: return None @@ -3666,7 +3668,7 @@ class PyMISP: return value return value - def _check_json_response(self, response: requests.Response) -> Dict: # type: ignore + def _check_json_response(self, response: requests.Response) -> dict: # type: ignore r = self._check_response(response, expect_json=True) if isinstance(r, (dict, list)): return r @@ -3680,7 +3682,7 @@ class PyMISP: else: raise MISPServerError(f'Error code {response.status_code} for HEAD request') - def _check_response(self, response: requests.Response, lenient_response_type: bool = False, expect_json: bool = False) -> Union[Dict, str]: + def _check_response(self, response: requests.Response, lenient_response_type: bool = False, expect_json: bool = False) -> dict | str: """Check if the response from the server is not an unexpected error""" if response.status_code >= 500: headers_without_auth = {i: response.request.headers[i] for i in response.request.headers if i != 'Authorization'} @@ -3722,7 +3724,7 @@ class PyMISP: def __repr__(self): return f'<{self.__class__.__name__}(url={self.root_url})' - def _prepare_request(self, request_type: str, url: str, data: Optional[Union[Iterable, Mapping, AbstractMISP, bytes]] = None, + def _prepare_request(self, request_type: str, url: str, data: Iterable | Mapping | AbstractMISP | bytes | None = None, params: Mapping = {}, kw_params: Mapping = {}, output_type: str = 'json', content_type: str = 'json') -> requests.Response: '''Prepare a request for python-requests''' @@ -3733,7 +3735,7 @@ class PyMISP: # so we need to make it a + instead and hope for the best url = url.replace(' ', '+') url = urljoin(self.root_url, url) - d: Optional[Union[bytes, str]] = None + d: bytes | str | None = None if data is not None: if isinstance(data, bytes): d = data @@ -3768,7 +3770,7 @@ class PyMISP: verify=self.ssl, cert=self.cert) return self.__session.send(prepped, timeout=self.timeout, **settings) - def _csv_to_dict(self, csv_content: str) -> List[dict]: + def _csv_to_dict(self, csv_content: str) -> list[dict]: '''Makes a list of dict out of a csv file (requires headers)''' fieldnames, lines = csv_content.split('\n', 1) fields = fieldnames.split(',') diff --git a/pymisp/exceptions.py b/pymisp/exceptions.py index 96f3544..2479bec 100644 --- a/pymisp/exceptions.py +++ b/pymisp/exceptions.py @@ -1,9 +1,9 @@ -# -*- coding: utf-8 -*- +from __future__ import annotations class PyMISPError(Exception): def __init__(self, message): - super(PyMISPError, self).__init__(message) + super().__init__(message) self.message = message diff --git a/pymisp/mispevent.py b/pymisp/mispevent.py index 9c1c3ff..899fadc 100644 --- a/pymisp/mispevent.py +++ b/pymisp/mispevent.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from datetime import timezone, datetime, date import copy import os @@ -11,7 +13,7 @@ from collections import defaultdict import logging import hashlib from pathlib import Path -from typing import List, Optional, Union, IO, Dict, Any +from typing import IO, Any import warnings try: @@ -53,25 +55,11 @@ def _make_datetime(value) -> datetime: # Timestamp value = datetime.fromtimestamp(value) elif isinstance(value, str): - if sys.version_info >= (3, 7): - try: - # faster - value = datetime.fromisoformat(value) - except Exception: - value = parse(value) - else: - try: - # faster - if '+' in value or value.find('-', 10) > -1: # date contains `-` char - value = datetime.strptime(value, "%Y-%m-%dT%H:%M:%S.%f%z") - elif '.' in value: - value = datetime.strptime(value, "%Y-%m-%dT%H:%M:%S.%f") - elif 'T' in value: - value = datetime.strptime(value, "%Y-%m-%dT%H:%M:%S") - else: - value = datetime.strptime(value, "%Y-%m-%d") - except Exception: - value = parse(value) + try: + # faster + value = datetime.fromisoformat(value) + except Exception: + value = parse(value) elif isinstance(value, datetime): pass elif isinstance(value, date): # NOTE: date has to be *after* datetime, or it will be overwritten @@ -85,7 +73,7 @@ def _make_datetime(value) -> datetime: return value -def make_bool(value: Optional[Union[bool, int, str, dict, list]]) -> bool: +def make_bool(value: bool | int | str | dict | list | None) -> bool: """Converts the supplied value to a boolean. :param value: Value to interpret as a boolean. An empty string, dict @@ -103,7 +91,7 @@ def make_bool(value: Optional[Union[bool, int, str, dict, list]]) -> bool: return False return True else: - raise PyMISPError('Unable to convert {} to a boolean.'.format(value)) + raise PyMISPError(f'Unable to convert {value} to a boolean.') class MISPOrganisation(AbstractMISP): @@ -118,7 +106,7 @@ class MISPOrganisation(AbstractMISP): def from_dict(self, **kwargs): if 'Organisation' in kwargs: kwargs = kwargs['Organisation'] - super(MISPOrganisation, self).from_dict(**kwargs) + super().from_dict(**kwargs) def __repr__(self) -> str: if hasattr(self, 'name'): @@ -147,7 +135,7 @@ class MISPSharingGroupOrg(AbstractMISP): return f'<{self.__class__.__name__}(Org={self.Organisation.name}, extend={self.extend})' return f'<{self.__class__.__name__}(NotInitialized)' - def _to_feed(self) -> Dict: + def _to_feed(self) -> dict: to_return = super()._to_feed() to_return['Organisation'] = self.Organisation._to_feed() return to_return @@ -159,14 +147,14 @@ class MISPSharingGroup(AbstractMISP): def __init__(self) -> None: super().__init__() self.name: str - self.SharingGroupOrg: List[MISPSharingGroupOrg] = [] + self.SharingGroupOrg: list[MISPSharingGroupOrg] = [] @property - def sgorgs(self) -> List[MISPSharingGroupOrg]: + def sgorgs(self) -> list[MISPSharingGroupOrg]: return self.SharingGroupOrg @sgorgs.setter - def sgorgs(self, sgorgs: List[MISPSharingGroupOrg]): + def sgorgs(self, sgorgs: list[MISPSharingGroupOrg]): if all(isinstance(x, MISPSharingGroupOrg) for x in sgorgs): self.SharingGroupOrg = sgorgs else: @@ -190,7 +178,7 @@ class MISPSharingGroup(AbstractMISP): return f'<{self.__class__.__name__}(name={self.name})>' return f'<{self.__class__.__name__}(NotInitialized)>' - def _to_feed(self) -> Dict: + def _to_feed(self) -> dict: to_return = super()._to_feed() to_return['SharingGroupOrg'] = [sgorg._to_feed() for sgorg in self.SharingGroupOrg] to_return['Organisation'].pop('id', None) @@ -240,7 +228,7 @@ class MISPSighting(AbstractMISP): """ if 'Sighting' in kwargs: kwargs = kwargs['Sighting'] - super(MISPSighting, self).from_dict(**kwargs) + super().from_dict(**kwargs) def __repr__(self) -> str: if hasattr(self, 'value'): @@ -249,7 +237,7 @@ class MISPSighting(AbstractMISP): return '<{self.__class__.__name__}(id={self.id})'.format(self=self) if hasattr(self, 'uuid'): return '<{self.__class__.__name__}(uuid={self.uuid})'.format(self=self) - return '<{self.__class__.__name__}(NotInitialized)'.format(self=self) + return f'<{self.__class__.__name__}(NotInitialized)' class MISPAttribute(AbstractMISP): @@ -257,7 +245,7 @@ class MISPAttribute(AbstractMISP): 'deleted', 'timestamp', 'to_ids', 'disable_correlation', 'first_seen', 'last_seen'} - def __init__(self, describe_types: Optional[Dict] = None, strict: bool = False): + def __init__(self, describe_types: dict | None = None, strict: bool = False): """Represents an Attribute :param describe_types: Use it if you want to overwrite the default describeTypes.json file (you don't) @@ -265,42 +253,42 @@ class MISPAttribute(AbstractMISP): """ super().__init__() if describe_types: - self.describe_types: Dict[str, Any] = describe_types - self.__categories: List[str] = self.describe_types['categories'] - self.__category_type_mapping: Dict[str, List[str]] = self.describe_types['category_type_mappings'] - self.__sane_default: Dict[str, Dict[str, Union[str, int]]] = self.describe_types['sane_defaults'] + self.describe_types: dict[str, Any] = describe_types + self.__categories: list[str] = self.describe_types['categories'] + self.__category_type_mapping: dict[str, list[str]] = self.describe_types['category_type_mappings'] + self.__sane_default: dict[str, dict[str, str | int]] = self.describe_types['sane_defaults'] self.__strict: bool = strict - self.data: Optional[BytesIO] = None + self.data: BytesIO | None = None self.first_seen: datetime self.last_seen: datetime self.uuid: str = str(uuid.uuid4()) - self.ShadowAttribute: List[MISPShadowAttribute] = [] + self.ShadowAttribute: list[MISPShadowAttribute] = [] self.SharingGroup: MISPSharingGroup - self.Sighting: List[MISPSighting] = [] - self.Tag: List[MISPTag] = [] - self.Galaxy: List[MISPGalaxy] = [] + self.Sighting: list[MISPSighting] = [] + self.Tag: list[MISPTag] = [] + self.Galaxy: list[MISPGalaxy] = [] # For search self.Event: MISPEvent - self.RelatedAttribute: List[MISPAttribute] + self.RelatedAttribute: list[MISPAttribute] # For malware sample - self._malware_binary: Optional[BytesIO] + self._malware_binary: BytesIO | None - def add_tag(self, tag: Optional[Union[str, MISPTag, Dict]] = None, **kwargs) -> MISPTag: + def add_tag(self, tag: str | MISPTag | dict | None = None, **kwargs) -> MISPTag: return super()._add_tag(tag, **kwargs) @property - def tags(self) -> List[MISPTag]: + def tags(self) -> list[MISPTag]: """Returns a list of tags associated to this Attribute""" return self.Tag @tags.setter - def tags(self, tags: List[MISPTag]): + def tags(self, tags: list[MISPTag]): """Set a list of prepared MISPTag.""" super()._set_tags(tags) - def add_galaxy(self, galaxy: Union['MISPGalaxy', dict, None] = None, **kwargs) -> 'MISPGalaxy': + def add_galaxy(self, galaxy: MISPGalaxy | dict | None = None, **kwargs) -> MISPGalaxy: """Add a galaxy to the Attribute, either by passing a MISPGalaxy or a dictionary""" if isinstance(galaxy, MISPGalaxy): self.galaxies.append(galaxy) @@ -317,11 +305,11 @@ class MISPAttribute(AbstractMISP): return misp_galaxy @property - def galaxies(self) -> List['MISPGalaxy']: + def galaxies(self) -> list[MISPGalaxy]: """Returns a list of galaxies associated to this Attribute""" return self.Galaxy - def _prepare_data(self, data: Optional[Union[Path, str, bytes, BytesIO]]): + def _prepare_data(self, data: Path | str | bytes | BytesIO | None): if not data: super().__setattr__('data', None) return @@ -369,10 +357,10 @@ class MISPAttribute(AbstractMISP): else: super().__setattr__(name, value) - def hash_values(self, algorithm: str = 'sha512') -> List[str]: + def hash_values(self, algorithm: str = 'sha512') -> list[str]: """Compute the hash of every value for fast lookups""" if algorithm not in hashlib.algorithms_available: - raise PyMISPError('The algorithm {} is not available for hashing.'.format(algorithm)) + raise PyMISPError(f'The algorithm {algorithm} is not available for hashing.') if '|' in self.type or self.type == 'malware-sample': hashes = [] for v in self.value.split('|'): @@ -394,7 +382,7 @@ class MISPAttribute(AbstractMISP): if not hasattr(self, 'timestamp'): self.timestamp = datetime.timestamp(datetime.now()) - def _to_feed(self, with_distribution=False) -> Dict: + def _to_feed(self, with_distribution=False) -> dict: if with_distribution: self._fields_for_feed.add('distribution') to_return = super()._to_feed() @@ -410,12 +398,12 @@ class MISPAttribute(AbstractMISP): return to_return @property - def known_types(self) -> List[str]: + def known_types(self) -> list[str]: """Returns a list of all the known MISP attributes types""" return self.describe_types['types'] @property - def malware_binary(self) -> Optional[BytesIO]: + def malware_binary(self) -> BytesIO | None: """Returns a BytesIO of the malware, if the attribute has one. Decrypts, unpacks and caches the binary on the first invocation, which may require some time for large attachments (~1s/MB). @@ -437,11 +425,11 @@ class MISPAttribute(AbstractMISP): return None @property - def shadow_attributes(self) -> List[MISPShadowAttribute]: + def shadow_attributes(self) -> list[MISPShadowAttribute]: return self.ShadowAttribute @shadow_attributes.setter - def shadow_attributes(self, shadow_attributes: List[MISPShadowAttribute]): + def shadow_attributes(self, shadow_attributes: list[MISPShadowAttribute]): """Set a list of prepared MISPShadowAttribute.""" if all(isinstance(x, MISPShadowAttribute) for x in shadow_attributes): self.ShadowAttribute = shadow_attributes @@ -449,11 +437,11 @@ class MISPAttribute(AbstractMISP): raise PyMISPError('All the attributes have to be of type MISPShadowAttribute.') @property - def sightings(self) -> List[MISPSighting]: + def sightings(self) -> list[MISPSighting]: return self.Sighting @sightings.setter - def sightings(self, sightings: List[MISPSighting]): + def sightings(self, sightings: list[MISPSighting]): """Set a list of prepared MISPSighting.""" if all(isinstance(x, MISPSighting) for x in sightings): self.Sighting = sightings @@ -468,7 +456,7 @@ class MISPAttribute(AbstractMISP): """Alias for add_shadow_attribute""" return self.add_shadow_attribute(shadow_attribute, **kwargs) - def add_shadow_attribute(self, shadow_attribute: Optional[Union[MISPShadowAttribute, Dict]] = None, **kwargs) -> MISPShadowAttribute: + def add_shadow_attribute(self, shadow_attribute: MISPShadowAttribute | dict | None = None, **kwargs) -> MISPShadowAttribute: """Add a shadow attribute to the attribute (by name or a MISPShadowAttribute object)""" if isinstance(shadow_attribute, MISPShadowAttribute): misp_shadow_attribute = shadow_attribute @@ -479,12 +467,12 @@ class MISPAttribute(AbstractMISP): misp_shadow_attribute = MISPShadowAttribute() misp_shadow_attribute.from_dict(**kwargs) else: - raise PyMISPError("The shadow_attribute is in an invalid format (can be either string, MISPShadowAttribute, or an expanded dict): {}".format(shadow_attribute)) + raise PyMISPError(f"The shadow_attribute is in an invalid format (can be either string, MISPShadowAttribute, or an expanded dict): {shadow_attribute}") self.shadow_attributes.append(misp_shadow_attribute) self.edited = True return misp_shadow_attribute - def add_sighting(self, sighting: Optional[Union[MISPSighting, dict]] = None, **kwargs) -> MISPSighting: + def add_sighting(self, sighting: MISPSighting | dict | None = None, **kwargs) -> MISPSighting: """Add a sighting to the attribute (by name or a MISPSighting object)""" if isinstance(sighting, MISPSighting): misp_sighting = sighting @@ -495,7 +483,7 @@ class MISPAttribute(AbstractMISP): misp_sighting = MISPSighting() misp_sighting.from_dict(**kwargs) else: - raise PyMISPError("The sighting is in an invalid format (can be either string, MISPShadowAttribute, or an expanded dict): {}".format(sighting)) + raise PyMISPError(f"The sighting is in an invalid format (can be either string, MISPShadowAttribute, or an expanded dict): {sighting}") self.sightings.append(misp_sighting) self.edited = True return misp_sighting @@ -553,13 +541,13 @@ class MISPAttribute(AbstractMISP): self.to_ids = make_bool(self.to_ids) if not isinstance(self.to_ids, bool): - raise NewAttributeError('{} is invalid, to_ids has to be True or False'.format(self.to_ids)) + raise NewAttributeError(f'{self.to_ids} is invalid, to_ids has to be True or False') self.distribution = kwargs.pop('distribution', None) if self.distribution is not None: self.distribution = int(self.distribution) if self.distribution not in [0, 1, 2, 3, 4, 5]: - raise NewAttributeError('{} is invalid, the distribution has to be in 0, 1, 2, 3, 4, 5'.format(self.distribution)) + raise NewAttributeError(f'{self.distribution} is invalid, the distribution has to be in 0, 1, 2, 3, 4, 5') # other possible values if kwargs.get('data'): @@ -578,10 +566,7 @@ class MISPAttribute(AbstractMISP): fs = kwargs.pop('first_seen') try: # Faster - if sys.version_info >= (3, 7): - self.first_seen = datetime.fromisoformat(fs) - else: - self.first_seen = datetime.strptime(fs, "%Y-%m-%dT%H:%M:%S.%f%z") + self.first_seen = datetime.fromisoformat(fs) except Exception: # Use __setattr__ self.first_seen = fs @@ -590,10 +575,7 @@ class MISPAttribute(AbstractMISP): ls = kwargs.pop('last_seen') try: # Faster - if sys.version_info >= (3, 7): - self.last_seen = datetime.fromisoformat(ls) - else: - self.last_seen = datetime.strptime(ls, "%Y-%m-%dT%H:%M:%S.%f%z") + self.last_seen = datetime.fromisoformat(ls) except Exception: # Use __setattr__ self.last_seen = ls @@ -607,7 +589,7 @@ class MISPAttribute(AbstractMISP): raise NewAttributeError('If the distribution is set to sharing group, a sharing group ID is required.') elif not self.sharing_group_id: # Cannot be None or 0 either. - raise NewAttributeError('If the distribution is set to sharing group, a sharing group ID is required (cannot be {}).'.format(self.sharing_group_id)) + raise NewAttributeError(f'If the distribution is set to sharing group, a sharing group ID is required (cannot be {self.sharing_group_id}).') if kwargs.get('Tag'): [self.add_tag(tag) for tag in kwargs.pop('Tag')] @@ -628,7 +610,7 @@ class MISPAttribute(AbstractMISP): super().from_dict(**kwargs) - def to_dict(self, json_format: bool = False) -> Dict: + def to_dict(self, json_format: bool = False) -> dict: to_return = super().to_dict(json_format) if self.data: to_return['data'] = base64.b64encode(self.data.getvalue()).decode() @@ -663,7 +645,7 @@ class MISPAttribute(AbstractMISP): def __repr__(self): if hasattr(self, 'value'): return '<{self.__class__.__name__}(type={self.type}, value={self.value})'.format(self=self) - return '<{self.__class__.__name__}(NotInitialized)'.format(self=self) + return f'<{self.__class__.__name__}(NotInitialized)' def verify(self, gpg_uid): # pragma: no cover # Not used @@ -719,12 +701,12 @@ class MISPObjectReference(AbstractMISP): def from_dict(self, **kwargs): if 'ObjectReference' in kwargs: kwargs = kwargs['ObjectReference'] - super(MISPObjectReference, self).from_dict(**kwargs) + super().from_dict(**kwargs) def __repr__(self) -> str: if hasattr(self, 'referenced_uuid') and hasattr(self, 'object_uuid'): return '<{self.__class__.__name__}(object_uuid={self.object_uuid}, referenced_uuid={self.referenced_uuid}, relationship_type={self.relationship_type})'.format(self=self) - return '<{self.__class__.__name__}(NotInitialized)'.format(self=self) + return f'<{self.__class__.__name__}(NotInitialized)' class MISPObject(AbstractMISP): @@ -733,7 +715,7 @@ class MISPObject(AbstractMISP): 'template_version', 'uuid', 'timestamp', 'comment', 'first_seen', 'last_seen', 'deleted'} - def __init__(self, name: str, strict: bool = False, standalone: bool = True, default_attributes_parameters: Dict = {}, **kwargs): + def __init__(self, name: str, strict: bool = False, standalone: bool = True, default_attributes_parameters: dict = {}, **kwargs): ''' Master class representing a generic MISP object :param name: Name of the object @@ -749,7 +731,7 @@ class MISPObject(AbstractMISP): self.name: str = name self._known_template: bool = False self.id: int - self._definition: Optional[Dict] + self._definition: dict | None misp_objects_template_custom = kwargs.pop('misp_objects_template_custom', None) misp_objects_path_custom = kwargs.pop('misp_objects_path_custom', None) @@ -763,9 +745,9 @@ class MISPObject(AbstractMISP): self.first_seen: datetime self.last_seen: datetime self.__fast_attribute_access: dict = defaultdict(list) # Hashtable object_relation: [attributes] - self.ObjectReference: List[MISPObjectReference] = [] + self.ObjectReference: list[MISPObjectReference] = [] self._standalone: bool = False - self.Attribute: List[MISPObjectAttribute] = [] + self.Attribute: list[MISPObjectAttribute] = [] self.SharingGroup: MISPSharingGroup self._default_attributes_parameters: dict if isinstance(default_attributes_parameters, MISPAttribute): @@ -794,7 +776,7 @@ class MISPObject(AbstractMISP): self.sharing_group_id = 0 self.standalone = standalone - def _load_template_path(self, template_path: Union[Path, str]) -> bool: + def _load_template_path(self, template_path: Path | str) -> bool: template = self._load_json(template_path) if not template: self._definition = None @@ -802,7 +784,7 @@ class MISPObject(AbstractMISP): self._load_template(template) return True - def _load_template(self, template: Dict) -> None: + def _load_template(self, template: dict) -> None: self._definition = template setattr(self, 'meta-category', self._definition['meta-category']) self.template_uuid = self._definition['uuid'] @@ -815,7 +797,7 @@ class MISPObject(AbstractMISP): if not hasattr(self, 'timestamp'): self.timestamp = datetime.timestamp(datetime.now()) - def _to_feed(self, with_distribution=False) -> Dict: + def _to_feed(self, with_distribution=False) -> dict: if with_distribution: self._fields_for_feed.add('distribution') if not hasattr(self, 'template_uuid'): # workaround for old events where the template_uuid was not yet mandatory @@ -824,7 +806,7 @@ class MISPObject(AbstractMISP): self.description = '' if not hasattr(self, 'meta-category'): # workaround for old events where meta-category is not always set setattr(self, 'meta-category', 'misc') - to_return = super(MISPObject, self)._to_feed() + to_return = super()._to_feed() if self.references: to_return['ObjectReference'] = [reference._to_feed() for reference in self.references] if with_distribution: @@ -844,12 +826,12 @@ class MISPObject(AbstractMISP): logger.warning(f'first_seen ({value}) has to be before last_seen ({self.last_seen})') super().__setattr__(name, value) - def force_misp_objects_path_custom(self, misp_objects_path_custom: Union[Path, str], object_name: Optional[str] = None): + def force_misp_objects_path_custom(self, misp_objects_path_custom: Path | str, object_name: str | None = None): if object_name: self.name = object_name self._set_template(misp_objects_path_custom) - def _set_template(self, misp_objects_path_custom: Optional[Union[Path, str]] = None, misp_objects_template_custom: Optional[Dict] = None): + def _set_template(self, misp_objects_path_custom: Path | str | None = None, misp_objects_template_custom: dict | None = None): if misp_objects_template_custom: # A complete template was given to the constructor self._load_template(misp_objects_template_custom) @@ -866,7 +848,7 @@ class MISPObject(AbstractMISP): self._known_template = self._load_template_path(self.misp_objects_path / self.name / 'definition.json') if not self._known_template and self._strict: - raise UnknownMISPObjectTemplate('{} is unknown in the MISP object directory.'.format(self.name)) + raise UnknownMISPObjectTemplate(f'{self.name} is unknown in the MISP object directory.') else: # Then we have no meta-category, template_uuid, description and template_version pass @@ -881,11 +863,11 @@ class MISPObject(AbstractMISP): self._strict = False @property - def attributes(self) -> List['MISPObjectAttribute']: + def attributes(self) -> list[MISPObjectAttribute]: return self.Attribute @attributes.setter - def attributes(self, attributes: List['MISPObjectAttribute']): + def attributes(self, attributes: list[MISPObjectAttribute]): if all(isinstance(x, MISPObjectAttribute) for x in attributes): self.Attribute = attributes self.__fast_attribute_access = defaultdict(list) @@ -893,11 +875,11 @@ class MISPObject(AbstractMISP): raise PyMISPError('All the attributes have to be of type MISPObjectAttribute.') @property - def references(self) -> List[MISPObjectReference]: + def references(self) -> list[MISPObjectReference]: return self.ObjectReference @references.setter - def references(self, references: List[MISPObjectReference]): + def references(self, references: list[MISPObjectReference]): if all(isinstance(x, MISPObjectReference) for x in references): self.ObjectReference = references else: @@ -941,7 +923,7 @@ class MISPObject(AbstractMISP): self.distribution = kwargs.pop('distribution') self.distribution = int(self.distribution) if self.distribution not in [0, 1, 2, 3, 4, 5]: - raise NewAttributeError('{} is invalid, the distribution has to be in 0, 1, 2, 3, 4, 5'.format(self.distribution)) + raise NewAttributeError(f'{self.distribution} is invalid, the distribution has to be in 0, 1, 2, 3, 4, 5') if kwargs.get('timestamp'): ts = kwargs.pop('timestamp') @@ -954,10 +936,7 @@ class MISPObject(AbstractMISP): fs = kwargs.pop('first_seen') try: # Faster - if sys.version_info >= (3, 7): - self.first_seen = datetime.fromisoformat(fs) - else: - self.first_seen = datetime.strptime(fs, "%Y-%m-%dT%H:%M:%S.%f%z") + self.first_seen = datetime.fromisoformat(fs) except Exception: # Use __setattr__ self.first_seen = fs @@ -966,10 +945,7 @@ class MISPObject(AbstractMISP): ls = kwargs.pop('last_seen') try: # Faster - if sys.version_info >= (3, 7): - self.last_seen = datetime.fromisoformat(ls) - else: - self.last_seen = datetime.strptime(ls, "%Y-%m-%dT%H:%M:%S.%f%z") + self.last_seen = datetime.fromisoformat(ls) except Exception: # Use __setattr__ self.last_seen = ls @@ -989,7 +965,7 @@ class MISPObject(AbstractMISP): super().from_dict(**kwargs) - def add_reference(self, referenced_uuid: Union[AbstractMISP, str], relationship_type: str, comment: Optional[str] = None, **kwargs) -> MISPObjectReference: + def add_reference(self, referenced_uuid: AbstractMISP | str, relationship_type: str, comment: str | None = None, **kwargs) -> MISPObjectReference: """Add a link (uuid) to another object""" if isinstance(referenced_uuid, AbstractMISP): # Allow to pass an object or an attribute instead of its UUID @@ -1011,22 +987,22 @@ class MISPObject(AbstractMISP): self.edited = True return reference - def get_attributes_by_relation(self, object_relation: str) -> List[MISPAttribute]: + def get_attributes_by_relation(self, object_relation: str) -> list[MISPAttribute]: '''Returns the list of attributes with the given object relation in the object''' return self._fast_attribute_access.get(object_relation, []) @property - def _fast_attribute_access(self) -> Dict: + def _fast_attribute_access(self) -> dict: if not self.__fast_attribute_access: for a in self.attributes: self.__fast_attribute_access[a.object_relation].append(a) return self.__fast_attribute_access - def has_attributes_by_relation(self, list_of_relations: List[str]) -> bool: + def has_attributes_by_relation(self, list_of_relations: list[str]) -> bool: '''True if all the relations in the list are defined in the object''' return all(relation in self._fast_attribute_access for relation in list_of_relations) - def add_attribute(self, object_relation: str, simple_value: Optional[Union[str, int, float]] = None, **value) -> Optional[MISPAttribute]: + def add_attribute(self, object_relation: str, simple_value: str | int | float | None = None, **value) -> MISPAttribute | None: """Add an attribute. :param object_relation: The object relation of the attribute you're adding to the object :param simple_value: The value @@ -1040,7 +1016,7 @@ class MISPObject(AbstractMISP): if simple_value is not None: # /!\ The value *can* be 0 value['value'] = simple_value if value.get('value') is None: - logger.warning("The value of the attribute you're trying to add is None, skipping it. Object relation: {}".format(object_relation)) + logger.warning(f"The value of the attribute you're trying to add is None, skipping it. Object relation: {object_relation}") return None else: if isinstance(value['value'], bytes): @@ -1056,14 +1032,14 @@ class MISPObject(AbstractMISP): if isinstance(value['value'], str): value['value'] = value['value'].strip().strip('\x00') if value['value'] == '': - logger.warning("The value of the attribute you're trying to add is an empty string, skipping it. Object relation: {}".format(object_relation)) + logger.warning(f"The value of the attribute you're trying to add is an empty string, skipping it. Object relation: {object_relation}") return None if self._known_template and self._definition: if object_relation in self._definition['attributes']: attribute = MISPObjectAttribute(self._definition['attributes'][object_relation]) else: # Woopsie, this object_relation is unknown, no sane defaults for you. - logger.warning("The template ({}) doesn't have the object_relation ({}) you're trying to add. If you are creating a new event to push to MISP, please review your code so it matches the template.".format(self.name, object_relation)) + logger.warning(f"The template ({self.name}) doesn't have the object_relation ({object_relation}) you're trying to add. If you are creating a new event to push to MISP, please review your code so it matches the template.") attribute = MISPObjectAttribute({}) else: attribute = MISPObjectAttribute({}) @@ -1074,7 +1050,7 @@ class MISPObject(AbstractMISP): self.edited = True return attribute - def add_attributes(self, object_relation: str, *attributes) -> List[Optional[MISPAttribute]]: + def add_attributes(self, object_relation: str, *attributes) -> list[MISPAttribute | None]: '''Add multiple attributes with the same object_relation. Helper for object_relation when multiple is True in the template. It is the same as calling multiple times add_attribute with the same object_relation. @@ -1088,15 +1064,15 @@ class MISPObject(AbstractMISP): to_return.append(a) return to_return - def to_dict(self, json_format: bool = False, strict: bool = False) -> Dict: + def to_dict(self, json_format: bool = False, strict: bool = False) -> dict: if strict or self._strict and self._known_template: self._validate() - return super(MISPObject, self).to_dict(json_format) + return super().to_dict(json_format) - def to_json(self, sort_keys: bool = False, indent: Optional[int] = None, strict: bool = False) -> str: + def to_json(self, sort_keys: bool = False, indent: int | None = None, strict: bool = False) -> str: if strict or self._strict and self._known_template: self._validate() - return super(MISPObject, self).to_json(sort_keys=sort_keys, indent=indent) + return super().to_json(sort_keys=sort_keys, indent=indent) def _validate(self) -> bool: if not self._definition: @@ -1105,7 +1081,7 @@ class MISPObject(AbstractMISP): if self._definition.get('required'): required_missing = set(self._definition['required']) - set(self._fast_attribute_access.keys()) if required_missing: - raise InvalidMISPObject('{} are required.'.format(required_missing)) + raise InvalidMISPObject(f'{required_missing} are required.') if self._definition.get('requiredOneOf'): if not set(self._definition['requiredOneOf']) & set(self._fast_attribute_access.keys()): # We ecpect at least one of the object_relation in requiredOneOf, and it isn't the case @@ -1116,13 +1092,13 @@ class MISPObject(AbstractMISP): continue if not self._definition['attributes'][rel].get('multiple'): # object_relation's here more than once, but it isn't allowed in the template. - raise InvalidMISPObject('Multiple occurrences of {} is not allowed'.format(rel)) + raise InvalidMISPObject(f'Multiple occurrences of {rel} is not allowed') return True def __repr__(self) -> str: if hasattr(self, 'name'): return '<{self.__class__.__name__}(name={self.name})'.format(self=self) - return '<{self.__class__.__name__}(NotInitialized)'.format(self=self) + return f'<{self.__class__.__name__}(NotInitialized)' class MISPEventReport(AbstractMISP): @@ -1137,7 +1113,7 @@ class MISPEventReport(AbstractMISP): if self.distribution is not None: self.distribution = int(self.distribution) if self.distribution not in [0, 1, 2, 3, 4, 5]: - raise NewEventReportError('{} is invalid, the distribution has to be in 0, 1, 2, 3, 4, 5'.format(self.distribution)) + raise NewEventReportError(f'{self.distribution} is invalid, the distribution has to be in 0, 1, 2, 3, 4, 5') if kwargs.get('sharing_group_id'): self.sharing_group_id = int(kwargs.pop('sharing_group_id')) @@ -1148,7 +1124,7 @@ class MISPEventReport(AbstractMISP): raise NewEventReportError('If the distribution is set to sharing group, a sharing group ID is required.') elif not self.sharing_group_id: # Cannot be None or 0 either. - raise NewEventReportError('If the distribution is set to sharing group, a sharing group ID is required (cannot be {}).'.format(self.sharing_group_id)) + raise NewEventReportError(f'If the distribution is set to sharing group, a sharing group ID is required (cannot be {self.sharing_group_id}).') self.name = kwargs.pop('name', None) if self.name is None: @@ -1176,7 +1152,7 @@ class MISPEventReport(AbstractMISP): def __repr__(self) -> str: if hasattr(self, 'name'): return '<{self.__class__.__name__}(name={self.name})'.format(self=self) - return '<{self.__class__.__name__}(NotInitialized)'.format(self=self) + return f'<{self.__class__.__name__}(NotInitialized)' def _set_default(self): if not hasattr(self, 'timestamp'): @@ -1204,7 +1180,7 @@ class MISPGalaxyClusterElement(AbstractMISP): def __repr__(self) -> str: if hasattr(self, 'key') and hasattr(self, 'value'): return '<{self.__class__.__name__}(key={self.key}, value={self.value})'.format(self=self) - return '<{self.__class__.__name__}(NotInitialized)'.format(self=self) + return f'<{self.__class__.__name__}(NotInitialized)' def __setattr__(self, key, value): if key == "value" and isinstance(value, list): @@ -1236,7 +1212,7 @@ class MISPGalaxyClusterRelation(AbstractMISP): def __repr__(self) -> str: if hasattr(self, "referenced_galaxy_cluster_type"): return '<{self.__class__.__name__}(referenced_galaxy_cluster_type={self.referenced_galaxy_cluster_type})'.format(self=self) - return '<{self.__class__.__name__}(NotInitialized)'.format(self=self) + return f'<{self.__class__.__name__}(NotInitialized)' def __init__(self) -> None: super().__init__() @@ -1244,7 +1220,7 @@ class MISPGalaxyClusterRelation(AbstractMISP): self.referenced_galaxy_cluster_uuid: str self.distribution: int = 0 self.referenced_galaxy_cluster_type: str - self.Tag: List[MISPTag] = [] + self.Tag: list[MISPTag] = [] def from_dict(self, **kwargs): # Default values for a valid event to send to a MISP instance @@ -1261,7 +1237,7 @@ class MISPGalaxyClusterRelation(AbstractMISP): raise NewGalaxyClusterRelationError('If the distribution is set to sharing group, a sharing group ID is required.') elif not self.sharing_group_id: # Cannot be None or 0 either. - raise NewGalaxyClusterRelationError('If the distribution is set to sharing group, a sharing group ID is required (cannot be {}).'.format(self.sharing_group_id)) + raise NewGalaxyClusterRelationError(f'If the distribution is set to sharing group, a sharing group ID is required (cannot be {self.sharing_group_id}).') if kwargs.get('id'): self.id = int(kwargs.pop('id')) @@ -1282,16 +1258,16 @@ class MISPGalaxyClusterRelation(AbstractMISP): self.SharingGroup.from_dict(**kwargs.pop('SharingGroup')) super().from_dict(**kwargs) - def add_tag(self, tag: Optional[Union[str, MISPTag, Dict]] = None, **kwargs) -> MISPTag: + def add_tag(self, tag: str | MISPTag | dict | None = None, **kwargs) -> MISPTag: return super()._add_tag(tag, **kwargs) @property - def tags(self) -> List[MISPTag]: + def tags(self) -> list[MISPTag]: """Returns a list of tags associated to this Attribute""" return self.Tag @tags.setter - def tags(self, tags: List[MISPTag]): + def tags(self, tags: list[MISPTag]): """Set a list of prepared MISPTag.""" super()._set_tags(tags) @@ -1321,9 +1297,9 @@ class MISPGalaxyCluster(AbstractMISP): def __init__(self) -> None: super().__init__() self.Galaxy: MISPGalaxy - self.GalaxyElement: List[MISPGalaxyClusterElement] = [] - self.meta: Dict = {} - self.GalaxyClusterRelation: List[MISPGalaxyClusterRelation] = [] + self.GalaxyElement: list[MISPGalaxyClusterElement] = [] + self.meta: dict = {} + self.GalaxyClusterRelation: list[MISPGalaxyClusterRelation] = [] self.Org: MISPOrganisation self.Orgc: MISPOrganisation self.SharingGroup: MISPSharingGroup @@ -1332,19 +1308,19 @@ class MISPGalaxyCluster(AbstractMISP): self.default = False @property - def cluster_elements(self) -> List[MISPGalaxyClusterElement]: + def cluster_elements(self) -> list[MISPGalaxyClusterElement]: return self.GalaxyElement @cluster_elements.setter - def cluster_elements(self, cluster_elements: List[MISPGalaxyClusterElement]): + def cluster_elements(self, cluster_elements: list[MISPGalaxyClusterElement]): self.GalaxyElement = cluster_elements @property - def cluster_relations(self) -> List[MISPGalaxyClusterRelation]: + def cluster_relations(self) -> list[MISPGalaxyClusterRelation]: return self.GalaxyClusterRelation @cluster_relations.setter - def cluster_relations(self, cluster_relations: List[MISPGalaxyClusterRelation]): + def cluster_relations(self, cluster_relations: list[MISPGalaxyClusterRelation]): self.GalaxyClusterRelation = cluster_relations def parse_meta_as_elements(self): @@ -1358,7 +1334,7 @@ class MISPGalaxyCluster(AbstractMISP): self.add_cluster_element(key=key, value=v) @property - def elements_meta(self) -> Dict: + def elements_meta(self) -> dict: """Function to return the galaxy cluster elements as a dictionary structure of lists that comes from a MISPGalaxy within a MISPEvent. Lossy, you lose the element ID """ @@ -1393,7 +1369,7 @@ class MISPGalaxyCluster(AbstractMISP): raise NewGalaxyClusterError('If the distribution is set to sharing group, a sharing group ID is required.') elif not self.sharing_group_id: # Cannot be None or 0 either. - raise NewGalaxyClusterError('If the distribution is set to sharing group, a sharing group ID is required (cannot be {}).'.format(self.sharing_group_id)) + raise NewGalaxyClusterError(f'If the distribution is set to sharing group, a sharing group ID is required (cannot be {self.sharing_group_id}).') if 'uuid' in kwargs: self.uuid = kwargs.pop('uuid') @@ -1431,7 +1407,7 @@ class MISPGalaxyCluster(AbstractMISP): self.cluster_elements.append(cluster_element) return cluster_element - def add_cluster_relation(self, referenced_galaxy_cluster_uuid: Union["MISPGalaxyCluster", str, UUID], referenced_galaxy_cluster_type: str, galaxy_cluster_uuid: Optional[str] = None, **kwargs: Dict) -> MISPGalaxyClusterRelation: + def add_cluster_relation(self, referenced_galaxy_cluster_uuid: MISPGalaxyCluster | str | UUID, referenced_galaxy_cluster_type: str, galaxy_cluster_uuid: str | None = None, **kwargs: dict) -> MISPGalaxyClusterRelation: """Add a cluster relation to a MISPGalaxyCluster. :param referenced_galaxy_cluster_uuid: UUID of the related cluster @@ -1461,7 +1437,7 @@ class MISPGalaxyCluster(AbstractMISP): def __repr__(self) -> str: if hasattr(self, 'value'): return '<{self.__class__.__name__}(value={self.value})'.format(self=self) - return '<{self.__class__.__name__}(NotInitialized)'.format(self=self) + return f'<{self.__class__.__name__}(NotInitialized)' class MISPGalaxy(AbstractMISP): @@ -1469,7 +1445,7 @@ class MISPGalaxy(AbstractMISP): def __init__(self) -> None: super().__init__() - self.GalaxyCluster: List[MISPGalaxyCluster] = [] + self.GalaxyCluster: list[MISPGalaxyCluster] = [] self.name: str def from_dict(self, **kwargs): @@ -1487,7 +1463,7 @@ class MISPGalaxy(AbstractMISP): super().from_dict(**kwargs) @property - def clusters(self) -> List[MISPGalaxyCluster]: + def clusters(self) -> list[MISPGalaxyCluster]: return self.GalaxyCluster def add_galaxy_cluster(self, **kwargs) -> MISPGalaxyCluster: @@ -1502,7 +1478,7 @@ class MISPGalaxy(AbstractMISP): def __repr__(self) -> str: if hasattr(self, 'name'): return '<{self.__class__.__name__}(name={self.name})'.format(self=self) - return '<{self.__class__.__name__}(NotInitialized)'.format(self=self) + return f'<{self.__class__.__name__}(NotInitialized)' class MISPEvent(AbstractMISP): @@ -1510,7 +1486,7 @@ class MISPEvent(AbstractMISP): _fields_for_feed: set = {'uuid', 'info', 'threat_level_id', 'analysis', 'timestamp', 'publish_timestamp', 'published', 'date', 'extends_uuid'} - def __init__(self, describe_types: Optional[Dict] = None, strict_validation: bool = False, **kwargs): + def __init__(self, describe_types: dict | None = None, strict_validation: bool = False, **kwargs): super().__init__(**kwargs) self.__schema_file = 'schema.json' if strict_validation else 'schema-lax.json' @@ -1520,25 +1496,25 @@ class MISPEvent(AbstractMISP): self.uuid: str = str(uuid.uuid4()) self.date: date - self.Attribute: List[MISPAttribute] = [] - self.Object: List[MISPObject] = [] - self.RelatedEvent: List[MISPEvent] = [] - self.ShadowAttribute: List[MISPShadowAttribute] = [] + self.Attribute: list[MISPAttribute] = [] + self.Object: list[MISPObject] = [] + self.RelatedEvent: list[MISPEvent] = [] + self.ShadowAttribute: list[MISPShadowAttribute] = [] self.SharingGroup: MISPSharingGroup - self.EventReport: List[MISPEventReport] = [] - self.Tag: List[MISPTag] = [] - self.Galaxy: List[MISPGalaxy] = [] + self.EventReport: list[MISPEventReport] = [] + self.Tag: list[MISPTag] = [] + self.Galaxy: list[MISPGalaxy] = [] - def add_tag(self, tag: Optional[Union[str, MISPTag, dict]] = None, **kwargs) -> MISPTag: + def add_tag(self, tag: str | MISPTag | dict | None = None, **kwargs) -> MISPTag: return super()._add_tag(tag, **kwargs) @property - def tags(self) -> List[MISPTag]: + def tags(self) -> list[MISPTag]: """Returns a list of tags associated to this Event""" return self.Tag @tags.setter - def tags(self, tags: List[MISPTag]): + def tags(self, tags: list[MISPTag]): """Set a list of prepared MISPTag.""" super()._set_tags(tags) @@ -1564,7 +1540,7 @@ class MISPEvent(AbstractMISP): self.threat_level_id = 4 @property - def manifest(self) -> Dict: + def manifest(self) -> dict: required = ['info', 'Orgc'] for r in required: if not hasattr(self, r): @@ -1584,8 +1560,8 @@ class MISPEvent(AbstractMISP): } } - def attributes_hashes(self, algorithm: str = 'sha512') -> List[str]: - to_return: List[str] = [] + def attributes_hashes(self, algorithm: str = 'sha512') -> list[str]: + to_return: list[str] = [] for attribute in self.attributes: to_return += attribute.hash_values(algorithm) for obj in self.objects: @@ -1593,7 +1569,7 @@ class MISPEvent(AbstractMISP): to_return += attribute.hash_values(algorithm) return to_return - def to_feed(self, valid_distributions: List[int] = [0, 1, 2, 3, 4, 5], with_meta: bool = False, with_distribution=False, with_local_tags: bool = True, with_event_reports: bool = True) -> Dict: + def to_feed(self, valid_distributions: list[int] = [0, 1, 2, 3, 4, 5], with_meta: bool = False, with_distribution=False, with_local_tags: bool = True, with_event_reports: bool = True) -> dict: """ Generate a json output for MISP Feed. :param valid_distributions: only makes sense if the distribution key is set; i.e., the event is exported from a MISP instance. @@ -1667,7 +1643,7 @@ class MISPEvent(AbstractMISP): return {'Event': to_return} @property - def known_types(self) -> List[str]: + def known_types(self) -> list[str]: return self.describe_types['types'] @property @@ -1686,68 +1662,68 @@ class MISPEvent(AbstractMISP): raise PyMISPError('Orgc must be of type MISPOrganisation.') @property - def attributes(self) -> List[MISPAttribute]: + def attributes(self) -> list[MISPAttribute]: return self.Attribute @attributes.setter - def attributes(self, attributes: List[MISPAttribute]): + def attributes(self, attributes: list[MISPAttribute]): if all(isinstance(x, MISPAttribute) for x in attributes): self.Attribute = attributes else: raise PyMISPError('All the attributes have to be of type MISPAttribute.') @property - def event_reports(self) -> List[MISPEventReport]: + def event_reports(self) -> list[MISPEventReport]: return self.EventReport @property - def shadow_attributes(self) -> List[MISPShadowAttribute]: + def shadow_attributes(self) -> list[MISPShadowAttribute]: return self.ShadowAttribute @shadow_attributes.setter - def shadow_attributes(self, shadow_attributes: List[MISPShadowAttribute]): + def shadow_attributes(self, shadow_attributes: list[MISPShadowAttribute]): if all(isinstance(x, MISPShadowAttribute) for x in shadow_attributes): self.ShadowAttribute = shadow_attributes else: raise PyMISPError('All the attributes have to be of type MISPShadowAttribute.') @property - def related_events(self) -> List['MISPEvent']: + def related_events(self) -> list[MISPEvent]: return self.RelatedEvent @property - def galaxies(self) -> List[MISPGalaxy]: + def galaxies(self) -> list[MISPGalaxy]: return self.Galaxy @galaxies.setter - def galaxies(self, galaxies: List[MISPGalaxy]): + def galaxies(self, galaxies: list[MISPGalaxy]): if all(isinstance(x, MISPGalaxy) for x in galaxies): self.Galaxy = galaxies else: raise PyMISPError('All the attributes have to be of type MISPGalaxy.') @property - def objects(self) -> List[MISPObject]: + def objects(self) -> list[MISPObject]: return self.Object @objects.setter - def objects(self, objects: List[MISPObject]): + def objects(self, objects: list[MISPObject]): if all(isinstance(x, MISPObject) for x in objects): self.Object = objects else: raise PyMISPError('All the attributes have to be of type MISPObject.') - def load_file(self, event_path: Union[Path, str], validate: bool = False, metadata_only: bool = False): + def load_file(self, event_path: Path | str, validate: bool = False, metadata_only: bool = False): """Load a JSON dump from a file on the disk""" if not os.path.exists(event_path): raise PyMISPError('Invalid path, unable to load the event.') with open(event_path, 'rb') as f: self.load(f, validate, metadata_only) - def load(self, json_event: Union[IO, str, bytes, dict], validate: bool = False, metadata_only: bool = False): + def load(self, json_event: IO | str | bytes | dict, validate: bool = False, metadata_only: bool = False): """Load a JSON dump from a pseudo file or a JSON string""" if isinstance(json_event, (BufferedIOBase, TextIOBase)): - json_event = json_event.read() # type: ignore + json_event = json_event.read() if isinstance(json_event, (str, bytes)): json_event = json.loads(json_event) @@ -1770,13 +1746,10 @@ class MISPEvent(AbstractMISP): if isinstance(value, date): pass elif isinstance(value, str): - if sys.version_info >= (3, 7): - try: - # faster - value = date.fromisoformat(value) - except Exception: - value = parse(value).date() - else: + try: + # faster + value = date.fromisoformat(value) + except Exception: value = parse(value).date() elif isinstance(value, (int, float)): value = date.fromtimestamp(value) @@ -1786,7 +1759,7 @@ class MISPEvent(AbstractMISP): raise NewEventError(f'Invalid format for the date: {type(value)} - {value}') super().__setattr__(name, value) - def set_date(self, d: Optional[Union[str, int, float, datetime, date]] = None, ignore_invalid: bool = False): + def set_date(self, d: str | int | float | datetime | date | None = None, ignore_invalid: bool = False): """Set a date for the event :param d: String, datetime, or date object @@ -1873,9 +1846,9 @@ class MISPEvent(AbstractMISP): self.SharingGroup = MISPSharingGroup() self.SharingGroup.from_dict(**kwargs.pop('SharingGroup')) - super(MISPEvent, self).from_dict(**kwargs) + super().from_dict(**kwargs) - def to_dict(self, json_format: bool = False) -> Dict: + def to_dict(self, json_format: bool = False) -> dict: to_return = super().to_dict(json_format) if to_return.get('date'): @@ -1904,17 +1877,17 @@ class MISPEvent(AbstractMISP): misp_shadow_attribute = MISPShadowAttribute() misp_shadow_attribute.from_dict(**kwargs) else: - raise PyMISPError("The shadow_attribute is in an invalid format (can be either string, MISPShadowAttribute, or an expanded dict): {}".format(shadow_attribute)) + raise PyMISPError(f"The shadow_attribute is in an invalid format (can be either string, MISPShadowAttribute, or an expanded dict): {shadow_attribute}") self.shadow_attributes.append(misp_shadow_attribute) self.edited = True return misp_shadow_attribute - def get_attribute_tag(self, attribute_identifier: str) -> List[MISPTag]: + def get_attribute_tag(self, attribute_identifier: str) -> list[MISPTag]: """Return the tags associated to an attribute or an object attribute. :param attribute_identifier: can be an ID, UUID, or the value. """ - tags: List[MISPTag] = [] + tags: list[MISPTag] = [] for a in self.attributes + [attribute for o in self.objects for attribute in o.attributes]: if ((hasattr(a, 'id') and a.id == attribute_identifier) or (hasattr(a, 'uuid') and a.uuid == attribute_identifier) @@ -1923,7 +1896,7 @@ class MISPEvent(AbstractMISP): tags += a.tags return tags - def add_attribute_tag(self, tag: Union[MISPTag, str], attribute_identifier: str) -> List[MISPAttribute]: + def add_attribute_tag(self, tag: MISPTag | str, attribute_identifier: str) -> list[MISPAttribute]: """Add a tag to an existing attribute. Raise an Exception if the attribute doesn't exist. :param tag: Tag name as a string, MISPTag instance, or dictionary @@ -1939,11 +1912,11 @@ class MISPEvent(AbstractMISP): attributes.append(a) if not attributes: - raise PyMISPError('No attribute with identifier {} found.'.format(attribute_identifier)) + raise PyMISPError(f'No attribute with identifier {attribute_identifier} found.') self.edited = True return attributes - def publish(self): + def publish(self) -> None: """Mark the attribute as published""" self.published = True @@ -1962,12 +1935,12 @@ class MISPEvent(AbstractMISP): a.delete() break else: - raise PyMISPError('No attribute with UUID/ID {} found.'.format(attribute_id)) + raise PyMISPError(f'No attribute with UUID/ID {attribute_id} found.') - def add_attribute(self, type: str, value: Union[str, int, float], **kwargs) -> Union[MISPAttribute, List[MISPAttribute]]: + def add_attribute(self, type: str, value: str | int | float, **kwargs) -> MISPAttribute | list[MISPAttribute]: """Add an attribute. type and value are required but you can pass all other parameters supported by MISPAttribute""" - attr_list: List[MISPAttribute] = [] + attr_list: list[MISPAttribute] = [] if isinstance(value, list): attr_list = [self.add_attribute(type=type, value=a, **kwargs) for a in value] else: @@ -1988,7 +1961,7 @@ class MISPEvent(AbstractMISP): self.edited = True return event_report - def add_galaxy(self, galaxy: Union[MISPGalaxy, dict, None] = None, **kwargs) -> MISPGalaxy: + def add_galaxy(self, galaxy: MISPGalaxy | dict | None = None, **kwargs) -> MISPGalaxy: """Add a galaxy and sub-clusters into an event, either by passing a MISPGalaxy or a dictionary. Supports all other parameters supported by MISPGalaxy""" @@ -2006,14 +1979,14 @@ class MISPEvent(AbstractMISP): self.galaxies.append(misp_galaxy) return misp_galaxy - def get_object_by_id(self, object_id: Union[str, int]) -> MISPObject: + def get_object_by_id(self, object_id: str | int) -> MISPObject: """Get an object by ID :param object_id: the ID is the one set by the server when creating the new object""" for obj in self.objects: if hasattr(obj, 'id') and int(obj.id) == int(object_id): return obj - raise InvalidMISPObject('Object with {} does not exist in this event'.format(object_id)) + raise InvalidMISPObject(f'Object with {object_id} does not exist in this event') def get_object_by_uuid(self, object_uuid: str) -> MISPObject: """Get an object by UUID @@ -2022,9 +1995,9 @@ class MISPEvent(AbstractMISP): for obj in self.objects: if hasattr(obj, 'uuid') and obj.uuid == object_uuid: return obj - raise InvalidMISPObject('Object with {} does not exist in this event'.format(object_uuid)) + raise InvalidMISPObject(f'Object with {object_uuid} does not exist in this event') - def get_objects_by_name(self, object_name: str) -> List[MISPObject]: + def get_objects_by_name(self, object_name: str) -> list[MISPObject]: """Get objects by name :param object_name: name is set by the server when creating the new object""" @@ -2034,7 +2007,7 @@ class MISPEvent(AbstractMISP): objects.append(obj) return objects - def add_object(self, obj: Union[MISPObject, dict, None] = None, **kwargs) -> MISPObject: + def add_object(self, obj: MISPObject | dict | None = None, **kwargs) -> MISPObject: """Add an object to the Event, either by passing a MISPObject, or a dictionary""" if isinstance(obj, MISPObject): misp_obj = obj @@ -2061,12 +2034,12 @@ class MISPEvent(AbstractMISP): :param object_id: ID or UUID """ for o in self.objects: - if ((hasattr(o, 'id') and o.id == object_id) + if ((hasattr(o, 'id') and int(o.id) == int(object_id)) or (hasattr(o, 'uuid') and o.uuid == object_id)): o.delete() break else: - raise PyMISPError('No object with UUID/ID {} found.'.format(object_id)) + raise PyMISPError(f'No object with UUID/ID {object_id} found.') def run_expansions(self): for index, attribute in enumerate(self.attributes): @@ -2078,7 +2051,7 @@ class MISPEvent(AbstractMISP): try: from .tools import make_binary_objects except ImportError as e: - logger.info('Unable to load make_binary_objects: {}'.format(e)) + logger.info(f'Unable to load make_binary_objects: {e}') continue file_object, bin_type_object, bin_section_objects = make_binary_objects(pseudofile=attribute.malware_binary, filename=attribute.malware_filename) self.add_object(file_object) @@ -2089,12 +2062,12 @@ class MISPEvent(AbstractMISP): self.add_object(bin_section_object) self.attributes.pop(index) else: - logger.warning('No expansions for this data type ({}). Open an issue if needed.'.format(attribute.type)) + logger.warning(f'No expansions for this data type ({attribute.type}). Open an issue if needed.') def __repr__(self) -> str: if hasattr(self, 'info'): return '<{self.__class__.__name__}(info={self.info})'.format(self=self) - return '<{self.__class__.__name__}(NotInitialized)'.format(self=self) + return f'<{self.__class__.__name__}(NotInitialized)' def _serialize(self): # pragma: no cover return '{date}{threat_level_id}{info}{uuid}{analysis}{timestamp}'.format( @@ -2165,12 +2138,12 @@ class MISPObjectTemplate(AbstractMISP): super().from_dict(**kwargs) def __repr__(self) -> str: - return '<{self.__class__.__name__}(self.name)'.format(self=self) + return f'<{self.__class__.__name__}(self.name)' class MISPUser(AbstractMISP): - def __init__(self, **kwargs: Dict) -> None: + def __init__(self, **kwargs: dict) -> None: super().__init__(**kwargs) self.email: str @@ -2178,13 +2151,13 @@ class MISPUser(AbstractMISP): if 'User' in kwargs: kwargs = kwargs['User'] super().from_dict(**kwargs) - if hasattr(self, 'password') and set(self.password) == set(['*']): + if hasattr(self, 'password') and set(self.password) == {'*'}: self.password = None def __repr__(self) -> str: if hasattr(self, 'email'): return '<{self.__class__.__name__}(email={self.email})'.format(self=self) - return '<{self.__class__.__name__}(NotInitialized)'.format(self=self) + return f'<{self.__class__.__name__}(NotInitialized)' class MISPFeed(AbstractMISP): @@ -2197,7 +2170,7 @@ class MISPFeed(AbstractMISP): try: self.settings = json.loads(self.settings) except json.decoder.JSONDecodeError as e: - logger.error("Failed to parse feed settings: {}".format(self.settings)) + logger.error(f"Failed to parse feed settings: {self.settings}") raise e @@ -2241,7 +2214,7 @@ class MISPCorrelationExclusion(AbstractMISP): class MISPRole(AbstractMISP): - def __init__(self, **kwargs: Dict) -> None: + def __init__(self, **kwargs: dict) -> None: super().__init__(**kwargs) self.perm_admin: int self.perm_site_admin: int @@ -2262,7 +2235,7 @@ class MISPServer(AbstractMISP): class MISPLog(AbstractMISP): - def __init__(self, **kwargs: Dict) -> None: + def __init__(self, **kwargs: dict) -> None: super().__init__(**kwargs) self.model: str self.action: str @@ -2279,7 +2252,7 @@ class MISPLog(AbstractMISP): class MISPEventDelegation(AbstractMISP): - def __init__(self, **kwargs: Dict) -> None: + def __init__(self, **kwargs: dict) -> None: super().__init__(**kwargs) self.org_id: int self.requester_org_id: int @@ -2304,7 +2277,7 @@ class MISPObjectAttribute(MISPAttribute): super().__init__() self._definition = definition - def from_dict(self, object_relation: str, value: Union[str, int, float], **kwargs): # type: ignore + def from_dict(self, object_relation: str, value: str | int | float, **kwargs): # type: ignore # NOTE: Signature of "from_dict" incompatible with supertype "MISPAttribute" self.object_relation = object_relation self.value = value @@ -2334,7 +2307,7 @@ class MISPObjectAttribute(MISPAttribute): def __repr__(self): if hasattr(self, 'value'): return '<{self.__class__.__name__}(object_relation={self.object_relation}, value={self.value})'.format(self=self) - return '<{self.__class__.__name__}(NotInitialized)'.format(self=self) + return f'<{self.__class__.__name__}(NotInitialized)' class MISPCommunity(AbstractMISP): @@ -2361,9 +2334,9 @@ class MISPUserSetting(AbstractMISP): class MISPInbox(AbstractMISP): - def __init__(self, **kwargs: Dict) -> None: + def __init__(self, **kwargs: dict) -> None: super().__init__(**kwargs) - self.data: Dict + self.data: dict def from_dict(self, **kwargs): if 'Inbox' in kwargs: @@ -2376,7 +2349,7 @@ class MISPInbox(AbstractMISP): class MISPEventBlocklist(AbstractMISP): - def __init__(self, **kwargs: Dict) -> None: + def __init__(self, **kwargs: dict) -> None: super().__init__(**kwargs) self.event_uuid: str @@ -2391,7 +2364,7 @@ class MISPEventBlocklist(AbstractMISP): class MISPOrganisationBlocklist(AbstractMISP): - def __init__(self, **kwargs: Dict) -> None: + def __init__(self, **kwargs: dict) -> None: super().__init__(**kwargs) self.org_uuid: str @@ -2406,7 +2379,7 @@ class MISPOrganisationBlocklist(AbstractMISP): class MISPDecayingModel(AbstractMISP): - def __init__(self, **kwargs: Dict) -> None: + def __init__(self, **kwargs: dict) -> None: super().__init__(**kwargs) self.uuid: str self.id: int diff --git a/pymisp/tools/__init__.py b/pymisp/tools/__init__.py index cd5c1c9..30ce253 100644 --- a/pymisp/tools/__init__.py +++ b/pymisp/tools/__init__.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from .vtreportobject import VTReportObject # noqa from .neo4j import Neo4j # noqa from .fileobject import FileObject # noqa diff --git a/pymisp/tools/_psl_faup.py b/pymisp/tools/_psl_faup.py index 18365a0..9a33bfd 100644 --- a/pymisp/tools/_psl_faup.py +++ b/pymisp/tools/_psl_faup.py @@ -1,5 +1,6 @@ #!/usr/bin/env python -# -*- coding: utf-8 -*- + +from __future__ import annotations import ipaddress import socket @@ -12,7 +13,7 @@ class UrlNotDecoded(Exception): pass -class PSLFaup(object): +class PSLFaup: """ Fake Faup Python Library using PSL for Windows support """ @@ -64,7 +65,7 @@ class PSLFaup(object): if not self.decoded: raise UrlNotDecoded("You must call faup.decode() first") - netloc = self.get_host() + ('' if self.get_port() is None else ':{}'.format(self.get_port())) + netloc = self.get_host() + ('' if self.get_port() is None else f':{self.get_port()}') return _ensure_bytes( urlunparse( (self.get_scheme(), netloc, self.get_resource_path(), diff --git a/pymisp/tools/abstractgenerator.py b/pymisp/tools/abstractgenerator.py index 582356e..6e4b51c 100644 --- a/pymisp/tools/abstractgenerator.py +++ b/pymisp/tools/abstractgenerator.py @@ -1,5 +1,6 @@ #!/usr/bin/env python -# -*- coding: utf-8 -*- + +from __future__ import annotations from .. import MISPObject from ..exceptions import InvalidMISPObject @@ -10,7 +11,7 @@ from typing import Union, Optional class AbstractMISPObjectGenerator(MISPObject): - def _detect_epoch(self, timestamp: Union[str, int, float]) -> bool: + def _detect_epoch(self, timestamp: str | int | float) -> bool: try: tmp = float(timestamp) if tmp < 30000000: @@ -21,7 +22,7 @@ class AbstractMISPObjectGenerator(MISPObject): except ValueError: return False - def _sanitize_timestamp(self, timestamp: Optional[Union[datetime, date, dict, str, int, float]] = None) -> datetime: + def _sanitize_timestamp(self, timestamp: datetime | date | dict | str | int | float | None = None) -> datetime: if not timestamp: return datetime.now() diff --git a/pymisp/tools/asnobject.py b/pymisp/tools/asnobject.py index 909d06b..ef237a2 100644 --- a/pymisp/tools/asnobject.py +++ b/pymisp/tools/asnobject.py @@ -1,5 +1,6 @@ #!/usr/bin/env python -# -*- coding: utf-8 -*- + +from __future__ import annotations from .abstractgenerator import AbstractMISPObjectGenerator import logging diff --git a/pymisp/tools/create_misp_object.py b/pymisp/tools/create_misp_object.py index 60a0ae8..7864905 100644 --- a/pymisp/tools/create_misp_object.py +++ b/pymisp/tools/create_misp_object.py @@ -1,5 +1,6 @@ #!/usr/bin/env python -# -*- coding: utf-8 -*- + +from __future__ import annotations from io import BytesIO @@ -31,7 +32,7 @@ class FileTypeNotImplemented(MISPObjectException): pass -def make_binary_objects(filepath: Optional[str] = None, pseudofile: Optional[BytesIO] = None, filename: Optional[str] = None, standalone: bool = True, default_attributes_parameters: dict = {}): +def make_binary_objects(filepath: str | None = None, pseudofile: BytesIO | None = None, filename: str | None = None, standalone: bool = True, default_attributes_parameters: dict = {}): misp_file = FileObject(filepath=filepath, pseudofile=pseudofile, filename=filename, standalone=standalone, default_attributes_parameters=default_attributes_parameters) if HAS_LIEF and (filepath or (pseudofile and filename)): diff --git a/pymisp/tools/csvloader.py b/pymisp/tools/csvloader.py index c5880ac..7d68f88 100644 --- a/pymisp/tools/csvloader.py +++ b/pymisp/tools/csvloader.py @@ -1,5 +1,6 @@ #!/usr/bin/env python3 -# -*- coding: utf-8 -*- + +from __future__ import annotations from pathlib import Path from typing import List, Optional @@ -10,7 +11,7 @@ from pymisp import MISPObject class CSVLoader(): - def __init__(self, template_name: str, csv_path: Path, fieldnames: Optional[List[str]] = None, has_fieldnames=False, + def __init__(self, template_name: str, csv_path: Path, fieldnames: list[str] | None = None, has_fieldnames=False, delimiter: str = ',', quotechar: str = '"'): self.template_name = template_name self.delimiter = delimiter diff --git a/pymisp/tools/domainipobject.py b/pymisp/tools/domainipobject.py index 2fe9a3e..1bed317 100644 --- a/pymisp/tools/domainipobject.py +++ b/pymisp/tools/domainipobject.py @@ -1,5 +1,6 @@ #!/usr/bin/env python -# -*- coding: utf-8 -*- + +from __future__ import annotations from .abstractgenerator import AbstractMISPObjectGenerator import logging diff --git a/pymisp/tools/elfobject.py b/pymisp/tools/elfobject.py index a26734b..664bc83 100644 --- a/pymisp/tools/elfobject.py +++ b/pymisp/tools/elfobject.py @@ -1,5 +1,6 @@ #!/usr/bin/env python3 -# -*- coding: utf-8 -*- + +from __future__ import annotations from .abstractgenerator import AbstractMISPObjectGenerator from ..exceptions import InvalidMISPObject @@ -32,7 +33,7 @@ def make_elf_objects(lief_parsed: lief.ELF.Binary, misp_file: FileObject, standa class ELFObject(AbstractMISPObjectGenerator): - def __init__(self, parsed: Optional[lief.ELF.Binary] = None, filepath: Optional[Union[Path, str]] = None, pseudofile: Optional[BytesIO] = None, **kwargs): + def __init__(self, parsed: lief.ELF.Binary | None = None, filepath: Path | str | None = None, pseudofile: BytesIO | None = None, **kwargs): """Creates an ELF object, with lief""" super().__init__('elf', **kwargs) if not HAS_PYDEEP: @@ -43,7 +44,7 @@ class ELFObject(AbstractMISPObjectGenerator): elif isinstance(pseudofile, bytes): self.__elf = lief.ELF.parse(raw=pseudofile) else: - raise InvalidMISPObject('Pseudo file can be BytesIO or bytes got {}'.format(type(pseudofile))) + raise InvalidMISPObject(f'Pseudo file can be BytesIO or bytes got {type(pseudofile)}') elif filepath: self.__elf = lief.ELF.parse(filepath) elif parsed: @@ -51,7 +52,7 @@ class ELFObject(AbstractMISPObjectGenerator): if isinstance(parsed, lief.ELF.Binary): self.__elf = parsed else: - raise InvalidMISPObject('Not a lief.ELF.Binary: {}'.format(type(parsed))) + raise InvalidMISPObject(f'Not a lief.ELF.Binary: {type(parsed)}') self.generate_attributes() def generate_attributes(self): @@ -68,7 +69,7 @@ class ELFObject(AbstractMISPObjectGenerator): if not section.name: continue s = ELFSectionObject(section, standalone=self._standalone, default_attributes_parameters=self._default_attributes_parameters) - self.add_reference(s.uuid, 'includes', 'Section {} of ELF'.format(pos)) + self.add_reference(s.uuid, 'includes', f'Section {pos} of ELF') pos += 1 self.sections.append(s) self.add_attribute('number-sections', value=len(self.sections)) @@ -80,7 +81,7 @@ class ELFSectionObject(AbstractMISPObjectGenerator): """Creates an ELF Section object. Object generated by ELFObject.""" # Python3 way # super().__init__('pe-section') - super(ELFSectionObject, self).__init__('elf-section', **kwargs) + super().__init__('elf-section', **kwargs) self.__section = section self.__data = bytes(self.__section.content) self.generate_attributes() diff --git a/pymisp/tools/emailobject.py b/pymisp/tools/emailobject.py index cb75941..21e2478 100644 --- a/pymisp/tools/emailobject.py +++ b/pymisp/tools/emailobject.py @@ -1,5 +1,6 @@ #!/usr/bin/env python3 -# -*- coding: utf-8 -*- + +from __future__ import annotations import re import logging @@ -29,14 +30,14 @@ class MISPMsgConverstionError(MISPObjectException): class EMailObject(AbstractMISPObjectGenerator): - def __init__(self, filepath: Optional[Union[Path, str]]=None, pseudofile: Optional[BytesIO]=None, + def __init__(self, filepath: Path | str | None=None, pseudofile: BytesIO | None=None, attach_original_email: bool = True, **kwargs): super().__init__('email', **kwargs) self.attach_original_email = attach_original_email - self.encapsulated_body: Union[str, None] = None - self.eml_from_msg: Union[bool, None] = None - self.raw_emails: Dict[str, Union[BytesIO, None]] = {'msg': None, + self.encapsulated_body: str | None = None + self.eml_from_msg: bool | None = None + self.raw_emails: dict[str, BytesIO | None] = {'msg': None, 'eml': None} self.__pseudofile = self.create_pseudofile(filepath, pseudofile) @@ -66,7 +67,7 @@ class EMailObject(AbstractMISPObjectGenerator): return message except ValueError as _e: # Exception logger.debug("Email not in .msg format or is a corrupted .msg. Attempting to decode email from other formats.") - logger.debug("Error: {} ".format(_e)) + logger.debug(f"Error: {_e} ") try: if content_in_bytes[:3] == b'\xef\xbb\xbf': # utf-8-sig byte-order mark (BOM) eml_bytes = content_in_bytes.decode("utf_8_sig").encode("utf-8") @@ -81,8 +82,8 @@ class EMailObject(AbstractMISPObjectGenerator): raise PyMISPNotImplementedYet("EmailObject does not know how to decode data passed to it. Object may not be an email. If this is an email please submit it as an issue to PyMISP so we can add support.") @staticmethod - def create_pseudofile(filepath: Optional[Union[Path, str]] = None, - pseudofile: Optional[BytesIO] = None) -> BytesIO: + def create_pseudofile(filepath: Path | str | None = None, + pseudofile: BytesIO | None = None) -> BytesIO: """Creates a pseudofile using directly passed data or data loaded from file path. """ if filepath: @@ -102,7 +103,7 @@ class EMailObject(AbstractMISPObjectGenerator): eml = self._build_eml(message, body, attachments) return eml - def _extract_msg_objects(self, msg_obj: MessageBase) -> Tuple[EmailMessage, Dict, List[Any]]: + def _extract_msg_objects(self, msg_obj: MessageBase) -> tuple[EmailMessage, dict, list[Any]]: """Extracts email objects needed to construct an eml from a msg.""" message: EmailMessage = email.message_from_string(msg_obj.header.as_string(), policy=policy.default) # type: ignore body = {} @@ -153,14 +154,14 @@ class EMailObject(AbstractMISPObjectGenerator): def _build_eml(self, message: EmailMessage, body: dict, attachments: list) -> EmailMessage: """Constructs an eml file from objects extracted from a msg.""" # Order the body objects by increasing complexity and toss any missing objects - body_objects: List[dict] = [body.get('text', {}), + body_objects: list[dict] = [body.get('text', {}), body.get('html', {}), body.get('rtf', {})] body_objects = [i for i in body_objects if i != {}] # If this a non-multipart email then we only need to attach the payload if message.get_content_maintype() != 'multipart': for _body in body_objects: - if "text/{0}".format(_body['subtype']) == message.get_content_type(): + if "text/{}".format(_body['subtype']) == message.get_content_type(): message.set_content(**_body) return message raise MISPMsgConverstionError("Unable to find appropriate eml payload in message body.") @@ -172,7 +173,7 @@ class EMailObject(AbstractMISPObjectGenerator): if isinstance(body.get('html', None), dict): _html = body.get('html', {}).get('obj') for attch in attachments: - if _html.find("cid:{0}".format(attch.cid)) != -1: + if _html.find(f"cid:{attch.cid}") != -1: _content_type = attch.getStringStream('__substg1.0_370E') maintype, subtype = _content_type.split("/", 1) related_content[attch.cid] = (attch, @@ -241,7 +242,7 @@ class EMailObject(AbstractMISPObjectGenerator): pass @property - def attachments(self) -> List[Tuple[Optional[str], BytesIO]]: + def attachments(self) -> list[tuple[str | None, BytesIO]]: to_return = [] try: for attachment in self.email.iter_attachments(): @@ -269,14 +270,14 @@ class EMailObject(AbstractMISPObjectGenerator): message = self.email for _pref, body in message._find_body(message, preferencelist=['plain', 'html']): - comment = "{0} body".format(body.get_content_type()) + comment = f"{body.get_content_type()} body" if self.encapsulated_body == body.get_content_type(): comment += " De-Encapsulated from RTF in original msg." self.add_attribute("email-body", body.get_content(), comment=comment) - headers = ["{}: {}".format(k, v) for k, v in message.items()] + headers = [f"{k}: {v}" for k, v in message.items()] if headers: self.add_attribute("header", "\n".join(headers)) @@ -331,20 +332,20 @@ class EMailObject(AbstractMISPObjectGenerator): for realname, address in email.utils.getaddresses([data]): if address and realname: - addresses.append({"value": address, "comment": "{} <{}>".format(realname, address)}) + addresses.append({"value": address, "comment": f"{realname} <{address}>"}) elif address: addresses.append({"value": address}) else: # parsing failed, skip continue if realname: - display_names.append({"value": realname, "comment": "{} <{}>".format(realname, address)}) + display_names.append({"value": realname, "comment": f"{realname} <{address}>"}) if addresses: self.add_attributes(typ, *addresses) if insert_display_names and display_names: try: - self.add_attributes("{}-display-name".format(typ), *display_names) + self.add_attributes(f"{typ}-display-name", *display_names) except NewAttributeError: # email object doesn't support display name for all email addrs pass diff --git a/pymisp/tools/ext_lookups.py b/pymisp/tools/ext_lookups.py index 75ca0e1..e1bf7c6 100644 --- a/pymisp/tools/ext_lookups.py +++ b/pymisp/tools/ext_lookups.py @@ -1,5 +1,6 @@ #!/usr/bin/env python -# -*- coding: utf-8 -*- + +from __future__ import annotations try: from pymispgalaxies import Clusters # type: ignore diff --git a/pymisp/tools/fail2banobject.py b/pymisp/tools/fail2banobject.py index 5a5a5b3..b714e27 100644 --- a/pymisp/tools/fail2banobject.py +++ b/pymisp/tools/fail2banobject.py @@ -1,5 +1,6 @@ #!/usr/bin/env python -# -*- coding: utf-8 -*- + +from __future__ import annotations from .abstractgenerator import AbstractMISPObjectGenerator import logging diff --git a/pymisp/tools/feed.py b/pymisp/tools/feed.py index f3d937a..9f7c084 100644 --- a/pymisp/tools/feed.py +++ b/pymisp/tools/feed.py @@ -1,5 +1,6 @@ #!/usr/bin/env python3 -# -*- coding: utf-8 -*- + +from __future__ import annotations from pathlib import Path from pymisp import MISPEvent @@ -9,7 +10,7 @@ from typing import List def feed_meta_generator(path: Path): manifests = {} - hashes: List[str] = [] + hashes: list[str] = [] for f_name in path.glob('*.json'): if str(f_name.name) == 'manifest.json': diff --git a/pymisp/tools/fileobject.py b/pymisp/tools/fileobject.py index ad2862b..696eeed 100644 --- a/pymisp/tools/fileobject.py +++ b/pymisp/tools/fileobject.py @@ -1,5 +1,6 @@ #!/usr/bin/env python3 -# -*- coding: utf-8 -*- + +from __future__ import annotations from ..exceptions import InvalidMISPObject from .abstractgenerator import AbstractMISPObjectGenerator @@ -22,7 +23,7 @@ except ImportError: HAS_PYDEEP = False try: - import magic # type: ignore + import magic HAS_MAGIC = True except ImportError: HAS_MAGIC = False @@ -30,7 +31,7 @@ except ImportError: class FileObject(AbstractMISPObjectGenerator): - def __init__(self, filepath: Optional[Union[Path, str]] = None, pseudofile: Optional[BytesIO] = None, filename: Optional[str] = None, **kwargs) -> None: + def __init__(self, filepath: Path | str | None = None, pseudofile: BytesIO | None = None, filename: str | None = None, **kwargs) -> None: super().__init__('file', **kwargs) if not HAS_PYDEEP: logger.warning("pydeep is missing, please install pymisp this way: pip install pymisp[fileobjects]") diff --git a/pymisp/tools/genericgenerator.py b/pymisp/tools/genericgenerator.py index eeed742..dbe6d50 100644 --- a/pymisp/tools/genericgenerator.py +++ b/pymisp/tools/genericgenerator.py @@ -1,5 +1,6 @@ #!/usr/bin/env python -# -*- coding: utf-8 -*- + +from __future__ import annotations from .abstractgenerator import AbstractMISPObjectGenerator from typing import List @@ -8,7 +9,7 @@ from typing import List class GenericObjectGenerator(AbstractMISPObjectGenerator): # FIXME: this method is different from the master one, and that's probably not a good idea. - def generate_attributes(self, attributes: List[dict]): # type: ignore + def generate_attributes(self, attributes: list[dict]): # type: ignore """Generates MISPObjectAttributes from a list of dictionaries. Each entry if the list must be in one of the two following formats: * {: } diff --git a/pymisp/tools/geolocationobject.py b/pymisp/tools/geolocationobject.py index 9ecb460..80a2aa1 100644 --- a/pymisp/tools/geolocationobject.py +++ b/pymisp/tools/geolocationobject.py @@ -1,5 +1,6 @@ #!/usr/bin/env python -# -*- coding: utf-8 -*- + +from __future__ import annotations from .abstractgenerator import AbstractMISPObjectGenerator import logging diff --git a/pymisp/tools/git_vuln_finder_object.py b/pymisp/tools/git_vuln_finder_object.py index 451d62a..50e3b72 100644 --- a/pymisp/tools/git_vuln_finder_object.py +++ b/pymisp/tools/git_vuln_finder_object.py @@ -1,5 +1,6 @@ #!/usr/bin/env python -# -*- coding: utf-8 -*- + +from __future__ import annotations from .abstractgenerator import AbstractMISPObjectGenerator import logging diff --git a/pymisp/tools/load_warninglists.py b/pymisp/tools/load_warninglists.py index 89ec192..8224a6c 100644 --- a/pymisp/tools/load_warninglists.py +++ b/pymisp/tools/load_warninglists.py @@ -1,5 +1,6 @@ #!/usr/bin/env python -# -*- coding: utf-8 -*- + +from __future__ import annotations try: from pymispwarninglists import WarningLists # type: ignore diff --git a/pymisp/tools/machoobject.py b/pymisp/tools/machoobject.py index 95f1b87..4a71db4 100644 --- a/pymisp/tools/machoobject.py +++ b/pymisp/tools/machoobject.py @@ -1,5 +1,6 @@ #!/usr/bin/env python3 -# -*- coding: utf-8 -*- + +from __future__ import annotations from ..exceptions import InvalidMISPObject from .abstractgenerator import AbstractMISPObjectGenerator @@ -32,7 +33,7 @@ def make_macho_objects(lief_parsed: lief.MachO.Binary, misp_file: FileObject, st class MachOObject(AbstractMISPObjectGenerator): - def __init__(self, parsed: Optional[lief.MachO.Binary] = None, filepath: Optional[Union[Path, str]] = None, pseudofile: Optional[BytesIO] = None, **kwargs): + def __init__(self, parsed: lief.MachO.Binary | None = None, filepath: Path | str | None = None, pseudofile: BytesIO | None = None, **kwargs): """Creates an MachO object, with lief""" super().__init__('macho', **kwargs) if not HAS_PYDEEP: @@ -43,7 +44,7 @@ class MachOObject(AbstractMISPObjectGenerator): elif isinstance(pseudofile, bytes): self.__macho = lief.MachO.parse(raw=pseudofile) else: - raise InvalidMISPObject('Pseudo file can be BytesIO or bytes got {}'.format(type(pseudofile))) + raise InvalidMISPObject(f'Pseudo file can be BytesIO or bytes got {type(pseudofile)}') elif filepath: self.__macho = lief.MachO.parse(filepath) elif parsed: @@ -51,7 +52,7 @@ class MachOObject(AbstractMISPObjectGenerator): if isinstance(parsed, lief.MachO.Binary): self.__macho = parsed else: - raise InvalidMISPObject('Not a lief.MachO.Binary: {}'.format(type(parsed))) + raise InvalidMISPObject(f'Not a lief.MachO.Binary: {type(parsed)}') self.generate_attributes() def generate_attributes(self): @@ -66,7 +67,7 @@ class MachOObject(AbstractMISPObjectGenerator): pos = 0 for section in self.__macho.sections: s = MachOSectionObject(section, standalone=self._standalone, default_attributes_parameters=self._default_attributes_parameters) - self.add_reference(s.uuid, 'includes', 'Section {} of MachO'.format(pos)) + self.add_reference(s.uuid, 'includes', f'Section {pos} of MachO') pos += 1 self.sections.append(s) self.add_attribute('number-sections', value=len(self.sections)) @@ -78,7 +79,7 @@ class MachOSectionObject(AbstractMISPObjectGenerator): """Creates an MachO Section object. Object generated by MachOObject.""" # Python3 way # super().__init__('pe-section') - super(MachOSectionObject, self).__init__('macho-section', **kwargs) + super().__init__('macho-section', **kwargs) self.__section = section self.__data = bytes(self.__section.content) self.generate_attributes() diff --git a/pymisp/tools/microblogobject.py b/pymisp/tools/microblogobject.py index 14adfb0..089877c 100644 --- a/pymisp/tools/microblogobject.py +++ b/pymisp/tools/microblogobject.py @@ -1,5 +1,6 @@ #!/usr/bin/env python -# -*- coding: utf-8 -*- + +from __future__ import annotations # NOTE: Reference on how this module is used: https://vvx7.io/posts/2020/05/misp-slack-bot/ diff --git a/pymisp/tools/neo4j.py b/pymisp/tools/neo4j.py index 2656a5b..ce479c1 100644 --- a/pymisp/tools/neo4j.py +++ b/pymisp/tools/neo4j.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +from __future__ import annotations import glob import os @@ -17,7 +17,7 @@ class Neo4j(): if not has_py2neo: raise Exception('py2neo is required, please install: pip install py2neo') authenticate(host, username, password) - self.graph = Graph("http://{}/db/data/".format(host)) + self.graph = Graph(f"http://{host}/db/data/") def load_events_directory(self, directory): self.events = [] diff --git a/pymisp/tools/openioc.py b/pymisp/tools/openioc.py index 662b444..488c5b0 100755 --- a/pymisp/tools/openioc.py +++ b/pymisp/tools/openioc.py @@ -1,5 +1,4 @@ - -# -*- coding: utf-8 -*- +from __future__ import annotations import os @@ -156,7 +155,7 @@ def extract_field(report, field_name): def load_openioc_file(openioc_path): if not os.path.exists(openioc_path): raise Exception("Path doesn't exists.") - with open(openioc_path, 'r') as f: + with open(openioc_path) as f: return load_openioc(f) diff --git a/pymisp/tools/peobject.py b/pymisp/tools/peobject.py index 167cfbf..151ed3b 100644 --- a/pymisp/tools/peobject.py +++ b/pymisp/tools/peobject.py @@ -1,5 +1,6 @@ #!/usr/bin/env python3 -# -*- coding: utf-8 -*- + +from __future__ import annotations from ..exceptions import InvalidMISPObject from .abstractgenerator import AbstractMISPObjectGenerator @@ -35,7 +36,7 @@ def make_pe_objects(lief_parsed: lief.PE.Binary, misp_file: FileObject, standalo class PEObject(AbstractMISPObjectGenerator): - def __init__(self, parsed: Optional[lief.PE.Binary] = None, filepath: Optional[Union[Path, str]] = None, pseudofile: Optional[BytesIO] = None, **kwargs): + def __init__(self, parsed: lief.PE.Binary | None = None, filepath: Path | str | None = None, pseudofile: BytesIO | None = None, **kwargs): """Creates an PE object, with lief""" super().__init__('pe', **kwargs) if not HAS_PYDEEP: @@ -46,7 +47,7 @@ class PEObject(AbstractMISPObjectGenerator): elif isinstance(pseudofile, bytes): self.__pe = lief.PE.parse(raw=pseudofile) else: - raise InvalidMISPObject('Pseudo file can be BytesIO or bytes got {}'.format(type(pseudofile))) + raise InvalidMISPObject(f'Pseudo file can be BytesIO or bytes got {type(pseudofile)}') elif filepath: self.__pe = lief.PE.parse(filepath) elif parsed: @@ -54,7 +55,7 @@ class PEObject(AbstractMISPObjectGenerator): if isinstance(parsed, lief.PE.Binary): self.__pe = parsed else: - raise InvalidMISPObject('Not a lief.PE.Binary: {}'.format(type(parsed))) + raise InvalidMISPObject(f'Not a lief.PE.Binary: {type(parsed)}') self.generate_attributes() def _is_exe(self): @@ -67,7 +68,7 @@ class PEObject(AbstractMISPObjectGenerator): def _is_driver(self): # List from pefile - system_DLLs = set(('ntoskrnl.exe', 'hal.dll', 'ndis.sys', 'bootvid.dll', 'kdcom.dll')) + system_DLLs = {'ntoskrnl.exe', 'hal.dll', 'ndis.sys', 'bootvid.dll', 'kdcom.dll'} if system_DLLs.intersection([imp.lower() for imp in self.__pe.libraries]): return True return False @@ -116,10 +117,10 @@ class PEObject(AbstractMISPObjectGenerator): # Skip section if name is none AND size is 0. continue s = PESectionObject(section, standalone=self._standalone, default_attributes_parameters=self._default_attributes_parameters) - self.add_reference(s.uuid, 'includes', 'Section {} of PE'.format(pos)) + self.add_reference(s.uuid, 'includes', f'Section {pos} of PE') if ((self.__pe.entrypoint >= section.virtual_address) and (self.__pe.entrypoint < (section.virtual_address + section.virtual_size))): - self.add_attribute('entrypoint-section-at-position', value='{}|{}'.format(section.name, pos)) + self.add_attribute('entrypoint-section-at-position', value=f'{section.name}|{pos}') pos += 1 self.sections.append(s) self.add_attribute('number-sections', value=len(self.sections)) diff --git a/pymisp/tools/reportlab_generator.py b/pymisp/tools/reportlab_generator.py index e3caf42..dc4f507 100644 --- a/pymisp/tools/reportlab_generator.py +++ b/pymisp/tools/reportlab_generator.py @@ -1,5 +1,6 @@ #!/usr/bin/env python -# -*- coding: utf-8 -*- + +from __future__ import annotations # Standard imports import base64 @@ -49,7 +50,7 @@ def create_flowable_tag(misp_tag): return [Flowable_Tag(text=misp_tag.name, color=misp_tag.colour, custom_style=col1_style)] -class Flowable_Tag(Flowable): +class Flowable_Tag(Flowable): # type: ignore[misc] """ Custom flowable to handle tags. Draw one Tag with the webview formatting Modified from : http://two.pairlist.net/pipermail/reportlab-users/2005-February/003695.html @@ -108,7 +109,7 @@ class Flowable_Tag(Flowable): LEFT_INTERNAL_PADDING = 2 ELONGATION = LEFT_INTERNAL_PADDING * 2 - p = Paragraph("{}".format(self.choose_good_text_color(), self.text), style=self.custom_style) + p = Paragraph(f"{self.text}", style=self.custom_style) string_width = stringWidth(self.text, self.custom_style.fontName, self.custom_style.fontSize) self.width = string_width + ELONGATION @@ -615,7 +616,7 @@ class Value_Formatter(): curr_uuid = str(is_safe_value(uuid)) curr_baseurl = self.config[moduleconfig[0]] curr_url = uuid_to_url(curr_baseurl, curr_uuid) - html_url = "{}".format(curr_url, safe_string(text)) + html_url = f"{safe_string(text)}" if color: # They want fancy colors @@ -744,7 +745,7 @@ class Value_Formatter(): answer = YES_ANSWER if is_safe_value(published_timestamp): # Published and have published date - answer += '({})'.format(published_timestamp.strftime(EXPORT_DATE_FORMAT)) + answer += f'({published_timestamp.strftime(EXPORT_DATE_FORMAT)})' else: # Published without published date answer += "(no date)" diff --git a/pymisp/tools/sbsignatureobject.py b/pymisp/tools/sbsignatureobject.py index ca7ad6e..35d8147 100644 --- a/pymisp/tools/sbsignatureobject.py +++ b/pymisp/tools/sbsignatureobject.py @@ -1,5 +1,6 @@ #!/usr/bin/env python3 -# -*- coding: utf-8 -*- + +from __future__ import annotations from .abstractgenerator import AbstractMISPObjectGenerator diff --git a/pymisp/tools/sshauthkeyobject.py b/pymisp/tools/sshauthkeyobject.py index 8d7d74c..d66cb1f 100644 --- a/pymisp/tools/sshauthkeyobject.py +++ b/pymisp/tools/sshauthkeyobject.py @@ -1,5 +1,6 @@ #!/usr/bin/env python3 -# -*- coding: utf-8 -*- + +from __future__ import annotations from ..exceptions import InvalidMISPObject from .abstractgenerator import AbstractMISPObjectGenerator @@ -13,11 +14,11 @@ logger = logging.getLogger('pymisp') class SSHAuthorizedKeysObject(AbstractMISPObjectGenerator): - def __init__(self, authorized_keys_path: Optional[Union[Path, str]] = None, authorized_keys_pseudofile: Optional[StringIO] = None, **kwargs): + def __init__(self, authorized_keys_path: Path | str | None = None, authorized_keys_pseudofile: StringIO | None = None, **kwargs): # PY3 way: super().__init__('ssh-authorized-keys', **kwargs) if authorized_keys_path: - with open(authorized_keys_path, 'r') as f: + with open(authorized_keys_path) as f: self.__pseudofile = StringIO(f.read()) elif authorized_keys_pseudofile and isinstance(authorized_keys_pseudofile, StringIO): self.__pseudofile = authorized_keys_pseudofile diff --git a/pymisp/tools/stix.py b/pymisp/tools/stix.py index 0c0f605..8f82459 100644 --- a/pymisp/tools/stix.py +++ b/pymisp/tools/stix.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +from __future__ import annotations try: from misp_stix_converter.converters.buildMISPAttribute import buildEvent # type: ignore diff --git a/pymisp/tools/update_objects.py b/pymisp/tools/update_objects.py index 2bcb6c7..abe1835 100644 --- a/pymisp/tools/update_objects.py +++ b/pymisp/tools/update_objects.py @@ -1,5 +1,6 @@ #!/usr/bin/env python3 -# -*- coding: utf-8 -*- + +from __future__ import annotations import zipfile from io import BytesIO diff --git a/pymisp/tools/urlobject.py b/pymisp/tools/urlobject.py index 485dfb7..956b0c9 100644 --- a/pymisp/tools/urlobject.py +++ b/pymisp/tools/urlobject.py @@ -1,5 +1,6 @@ #!/usr/bin/env python -# -*- coding: utf-8 -*- + +from __future__ import annotations from .abstractgenerator import AbstractMISPObjectGenerator import logging diff --git a/pymisp/tools/vehicleobject.py b/pymisp/tools/vehicleobject.py index 7d5bc95..da72f78 100644 --- a/pymisp/tools/vehicleobject.py +++ b/pymisp/tools/vehicleobject.py @@ -1,5 +1,7 @@ #!/usr/bin/python3 +from __future__ import annotations + import requests import json @@ -66,7 +68,7 @@ class VehicleObject(AbstractMISPObjectGenerator): self.add_attribute('image-url', type='text', value=ImageUrl) def _query(self): - payload = "RegistrationNumber={}&username={}".format(self._registration, self._username) + payload = f"RegistrationNumber={self._registration}&username={self._username}" headers = { 'Content-Type': "application/x-www-form-urlencoded", 'cache-control': "no-cache", diff --git a/pymisp/tools/vtreportobject.py b/pymisp/tools/vtreportobject.py index 4974fdb..1ad7654 100644 --- a/pymisp/tools/vtreportobject.py +++ b/pymisp/tools/vtreportobject.py @@ -1,5 +1,6 @@ #!/usr/bin/env python3 -# -*- coding: utf-8 -*- + +from __future__ import annotations import re from typing import Optional @@ -24,7 +25,7 @@ class VTReportObject(AbstractMISPObjectGenerator): :indicator: IOC to search VirusTotal for ''' - def __init__(self, apikey: str, indicator: str, vt_proxies: Optional[dict] = None, **kwargs): + def __init__(self, apikey: str, indicator: str, vt_proxies: dict | None = None, **kwargs): super().__init__('virustotal-report', **kwargs) indicator = indicator.strip() self._resource_type = self.__validate_resource(indicator) @@ -33,7 +34,7 @@ class VTReportObject(AbstractMISPObjectGenerator): self._report = self.__query_virustotal(apikey, indicator) self.generate_attributes() else: - error_msg = "A valid indicator is required. (One of type url, md5, sha1, sha256). Received '{}' instead".format(indicator) + error_msg = f"A valid indicator is required. (One of type url, md5, sha1, sha256). Received '{indicator}' instead" raise InvalidMISPObject(error_msg) def get_report(self): @@ -70,7 +71,7 @@ class VTReportObject(AbstractMISPObjectGenerator): :resource: Indicator to search in VirusTotal ''' - url = "https://www.virustotal.com/vtapi/v2/{}/report".format(self._resource_type) + url = f"https://www.virustotal.com/vtapi/v2/{self._resource_type}/report" params = {"apikey": apikey, "resource": resource} # for now assume we're using a public API key - we'll figure out private keys later if self._proxies: diff --git a/tests/testlive_comprehensive.py b/tests/testlive_comprehensive.py index aed4950..6aab0ec 100644 --- a/tests/testlive_comprehensive.py +++ b/tests/testlive_comprehensive.py @@ -1,5 +1,4 @@ #!/usr/bin/env python3 -# -*- coding: utf-8 -*- import os import sys @@ -13,7 +12,7 @@ import json from pathlib import Path import hashlib -import urllib3 # type: ignore +import urllib3 import time from uuid import uuid4 @@ -31,11 +30,7 @@ try: from pymisp.tools import CSVLoader, DomainIPObject, ASNObject, GenericObjectGenerator from pymisp.exceptions import MISPServerError except ImportError: - if sys.version_info < (3, 6): - print('This test suite requires Python 3.6+, breaking.') - sys.exit(0) - else: - raise + raise try: from keys import url, key # type: ignore diff --git a/tests/testlive_sync.py b/tests/testlive_sync.py index 24971c4..768ba31 100644 --- a/tests/testlive_sync.py +++ b/tests/testlive_sync.py @@ -1,23 +1,18 @@ #!/usr/bin/env python3 -# -*- coding: utf-8 -*- import time import sys import unittest import subprocess -import urllib3 # type: ignore +import urllib3 import logging logging.disable(logging.CRITICAL) try: from pymisp import ExpandedPyMISP, MISPOrganisation, MISPUser, MISPEvent, MISPObject, MISPSharingGroup, Distribution except ImportError: - if sys.version_info < (3, 6): - print('This test suite requires Python 3.6+, breaking.') - sys.exit(0) - else: - raise + raise key = 'eYQdGTEWZJ8C2lm9EpnMqxQGwGiPNyoR75JvLdlE' verifycert = False From 989731cbbe0a853d0fc77d33a09ff629d578b28c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Vinot?= Date: Wed, 17 Jan 2024 13:34:56 +0100 Subject: [PATCH 39/80] chg: New annotations in tests --- tests/test_emailobject.py | 7 ++--- tests/test_fileobject.py | 3 ++- tests/test_mispevent.py | 45 +++++++++++++++++---------------- tests/test_reportlab.py | 3 ++- tests/testlive_comprehensive.py | 2 ++ tests/testlive_sync.py | 2 ++ 6 files changed, 35 insertions(+), 27 deletions(-) diff --git a/tests/test_emailobject.py b/tests/test_emailobject.py index dce618d..bd3ae93 100644 --- a/tests/test_emailobject.py +++ b/tests/test_emailobject.py @@ -1,4 +1,6 @@ -import json +from __future__ import annotations + +# import json import unittest from email.message import EmailMessage @@ -146,7 +148,6 @@ class TestEmailObject(unittest.TestCase): if not isinstance(found_error, PyMISPNotImplementedYet): self.fail("Expected PyMISPNotImplementedYet when EmailObject receives completely unknown binary input data in a pseudofile. But, did not get that exception.") - @staticmethod - def _get_values(obj: EMailObject, relation: str) -> List[str]: + def _get_values(obj: EMailObject, relation: str) -> list[str]: return [attr.value for attr in obj.attributes if attr['object_relation'] == relation] diff --git a/tests/test_fileobject.py b/tests/test_fileobject.py index 9b6e80d..6d4b5aa 100644 --- a/tests/test_fileobject.py +++ b/tests/test_fileobject.py @@ -1,5 +1,6 @@ #!/usr/bin/env python -# -*- coding: utf-8 -*- + +from __future__ import annotations import unittest import json diff --git a/tests/test_mispevent.py b/tests/test_mispevent.py index 7d27a18..b5b79e9 100644 --- a/tests/test_mispevent.py +++ b/tests/test_mispevent.py @@ -1,5 +1,6 @@ #!/usr/bin/env python -# -*- coding: utf-8 -*- + +from __future__ import annotations import unittest import json @@ -28,7 +29,7 @@ class TestMISPEvent(unittest.TestCase): self.mispevent.set_date("2017-12-31") # test the set date method def test_simple(self): - with open('tests/mispevent_testfiles/simple.json', 'r') as f: + with open('tests/mispevent_testfiles/simple.json') as f: ref_json = json.load(f) del self.mispevent.uuid self.assertEqual(self.mispevent.to_json(sort_keys=True, indent=2), json.dumps(ref_json, sort_keys=True, indent=2)) @@ -36,14 +37,14 @@ class TestMISPEvent(unittest.TestCase): def test_event(self): self.init_event() self.mispevent.publish() - with open('tests/mispevent_testfiles/event.json', 'r') as f: + with open('tests/mispevent_testfiles/event.json') as f: ref_json = json.load(f) del self.mispevent.uuid self.assertEqual(self.mispevent.to_json(sort_keys=True, indent=2), json.dumps(ref_json, sort_keys=True, indent=2)) def test_loadfile(self): self.mispevent.load_file('tests/mispevent_testfiles/event.json') - with open('tests/mispevent_testfiles/event.json', 'r') as f: + with open('tests/mispevent_testfiles/event.json') as f: ref_json = json.load(f) del self.mispevent.uuid self.assertEqual(self.mispevent.to_json(sort_keys=True, indent=2), json.dumps(ref_json, sort_keys=True, indent=2)) @@ -63,14 +64,14 @@ class TestMISPEvent(unittest.TestCase): new_tag = MISPTag() new_tag.from_dict(name='foo') self.mispevent.add_tag(new_tag) - with open('tests/mispevent_testfiles/event_tags.json', 'r') as f: + with open('tests/mispevent_testfiles/event_tags.json') as f: ref_json = json.load(f) del self.mispevent.uuid self.assertEqual(self.mispevent.to_json(sort_keys=True, indent=2), json.dumps(ref_json, sort_keys=True, indent=2)) def test_event_galaxy(self): self.init_event() - with open('tests/mispevent_testfiles/galaxy.json', 'r') as f: + with open('tests/mispevent_testfiles/galaxy.json') as f: galaxy = json.load(f) misp_galaxy = MISPGalaxy() misp_galaxy.from_dict(**galaxy) @@ -85,20 +86,20 @@ class TestMISPEvent(unittest.TestCase): attr_tags = self.mispevent.get_attribute_tag('bar.exe') self.assertEqual(self.mispevent.attributes[0].tags[0].name, 'osint') self.assertEqual(attr_tags[0].name, 'osint') - with open('tests/mispevent_testfiles/attribute.json', 'r') as f: + with open('tests/mispevent_testfiles/attribute.json') as f: ref_json = json.load(f) del self.mispevent.uuid self.assertEqual(self.mispevent.to_json(sort_keys=True, indent=2), json.dumps(ref_json, sort_keys=True, indent=2)) # Fake setting an attribute ID for testing self.mispevent.attributes[0].id = 42 self.mispevent.delete_attribute(42) - with open('tests/mispevent_testfiles/attribute_del.json', 'r') as f: + with open('tests/mispevent_testfiles/attribute_del.json') as f: ref_json = json.load(f) self.assertEqual(self.mispevent.to_json(sort_keys=True, indent=2), json.dumps(ref_json, sort_keys=True, indent=2)) def test_attribute_galaxy(self): self.init_event() - with open('tests/mispevent_testfiles/galaxy.json', 'r') as f: + with open('tests/mispevent_testfiles/galaxy.json') as f: galaxy = json.load(f) misp_galaxy = MISPGalaxy() misp_galaxy.from_dict(**galaxy) @@ -139,7 +140,7 @@ class TestMISPEvent(unittest.TestCase): reference = self.mispevent.objects[0].add_reference(self.mispevent.objects[1], 'baz', comment='foo') del reference.uuid self.assertEqual(self.mispevent.objects[0].references[0].relationship_type, 'baz') - with open('tests/mispevent_testfiles/event_obj_attr_tag.json', 'r') as f: + with open('tests/mispevent_testfiles/event_obj_attr_tag.json') as f: ref_json = json.load(f) del self.mispevent.uuid self.assertEqual(self.mispevent.to_json(sort_keys=True, indent=2), json.dumps(ref_json, sort_keys=True, indent=2)) @@ -150,7 +151,7 @@ class TestMISPEvent(unittest.TestCase): self.mispevent.objects[0].add_attribute('filename', value='bar') self.mispevent.objects[0].add_tag('osint') self.mispevent.objects[0].uuid = 'a' - with open('tests/mispevent_testfiles/event_obj_tag.json', 'r') as f: + with open('tests/mispevent_testfiles/event_obj_tag.json') as f: ref_json = json.load(f) self.assertEqual(self.mispevent.to_json(sort_keys=True, indent=2), json.dumps(ref_json, sort_keys=True, indent=2)) @@ -160,7 +161,7 @@ class TestMISPEvent(unittest.TestCase): misp_object.add_attribute('username', 'adulau') misp_object.add_attribute('repository', 'cve-search') self.mispevent.add_object(misp_object) - with open('tests/mispevent_testfiles/galaxy.json', 'r') as f: + with open('tests/mispevent_testfiles/galaxy.json') as f: galaxy = json.load(f) misp_galaxy = MISPGalaxy() misp_galaxy.from_dict(**galaxy) @@ -178,7 +179,7 @@ class TestMISPEvent(unittest.TestCase): del a.uuid attribute = self.mispevent.attributes[0] self.assertEqual(attribute.malware_binary, pseudofile) - with open('tests/mispevent_testfiles/malware.json', 'r') as f: + with open('tests/mispevent_testfiles/malware.json') as f: ref_json = json.load(f) del self.mispevent.uuid self.assertEqual(self.mispevent.to_json(sort_keys=True, indent=2), json.dumps(ref_json, sort_keys=True, indent=2)) @@ -194,20 +195,20 @@ class TestMISPEvent(unittest.TestCase): def test_sighting(self): sighting = MISPSighting() sighting.from_dict(value='1', type='bar', timestamp=11111111) - with open('tests/mispevent_testfiles/sighting.json', 'r') as f: + with open('tests/mispevent_testfiles/sighting.json') as f: ref_json = json.load(f) self.assertEqual(sighting.to_json(sort_keys=True, indent=2), json.dumps(ref_json, sort_keys=True, indent=2)) def test_existing_event(self): self.mispevent.load_file('tests/mispevent_testfiles/existing_event.json') - with open('tests/mispevent_testfiles/existing_event.json', 'r') as f: + with open('tests/mispevent_testfiles/existing_event.json') as f: ref_json = json.load(f) self.assertEqual(self.mispevent.to_json(sort_keys=True, indent=2), json.dumps(ref_json, sort_keys=True, indent=2)) def test_shadow_attributes_existing(self): self.mispevent.load_file('tests/mispevent_testfiles/shadow.json') - with open('tests/mispevent_testfiles/shadow.json', 'r') as f: + with open('tests/mispevent_testfiles/shadow.json') as f: ref_json = json.load(f) self.assertEqual(self.mispevent.to_json(sort_keys=True, indent=2), json.dumps(ref_json, sort_keys=True, indent=2)) @@ -220,7 +221,7 @@ class TestMISPEvent(unittest.TestCase): del a.uuid p = self.mispevent.attributes[0].add_proposal(type='filename', value='bar.pdf') del p.uuid - with open('tests/mispevent_testfiles/proposals.json', 'r') as f: + with open('tests/mispevent_testfiles/proposals.json') as f: ref_json = json.load(f) self.assertEqual(self.mispevent.to_json(sort_keys=True, indent=2), json.dumps(ref_json, sort_keys=True, indent=2)) @@ -236,7 +237,7 @@ class TestMISPEvent(unittest.TestCase): del a.uuid self.mispevent.objects[0].uuid = 'a' self.mispevent.objects[1].uuid = 'b' - with open('tests/mispevent_testfiles/event_obj_def_param.json', 'r') as f: + with open('tests/mispevent_testfiles/event_obj_def_param.json') as f: ref_json = json.load(f) del self.mispevent.uuid self.assertEqual(self.mispevent.to_json(sort_keys=True, indent=2), json.dumps(ref_json, sort_keys=True, indent=2)) @@ -253,7 +254,7 @@ class TestMISPEvent(unittest.TestCase): a = self.mispevent.objects[0].add_attribute('nameserver', value='ns2.example.com', disable_correlation=False, to_ids=True, category='External analysis') del a.uuid self.mispevent.objects[0].uuid = 'a' - with open('tests/mispevent_testfiles/def_param.json', 'r') as f: + with open('tests/mispevent_testfiles/def_param.json') as f: ref_json = json.load(f) del self.mispevent.uuid self.assertEqual(self.mispevent.to_json(sort_keys=True, indent=2), json.dumps(ref_json, sort_keys=True, indent=2)) @@ -332,7 +333,7 @@ class TestMISPEvent(unittest.TestCase): self.assertTrue(self.mispevent.objects[0].attributes[0].edited) self.assertTrue(self.mispevent.objects[0].edited) self.assertTrue(self.mispevent.edited) - with open('tests/mispevent_testfiles/existing_event_edited.json', 'r') as f: + with open('tests/mispevent_testfiles/existing_event_edited.json') as f: ref_json = json.load(f) self.assertEqual(self.mispevent.to_json(sort_keys=True, indent=2), json.dumps(ref_json, sort_keys=True, indent=2)) @@ -370,7 +371,7 @@ class TestMISPEvent(unittest.TestCase): self.mispevent.objects[0].attributes = self.mispevent.objects[0].attributes[:2] self.mispevent.objects[0].uuid = 'a' - with open('tests/mispevent_testfiles/misp_custom_obj.json', 'r') as f: + with open('tests/mispevent_testfiles/misp_custom_obj.json') as f: ref_json = json.load(f) del self.mispevent.uuid self.assertEqual(self.mispevent.to_json(sort_keys=True, indent=2), json.dumps(ref_json, sort_keys=True, indent=2)) @@ -401,7 +402,7 @@ class TestMISPEvent(unittest.TestCase): self.mispevent.objects[0].attributes = self.mispevent.objects[0].attributes[:2] self.mispevent.objects[0].uuid = 'a' - with open('tests/mispevent_testfiles/misp_custom_obj.json', 'r') as f: + with open('tests/mispevent_testfiles/misp_custom_obj.json') as f: ref_json = json.load(f) del self.mispevent.uuid self.assertEqual(self.mispevent.to_json(sort_keys=True, indent=2), json.dumps(ref_json, sort_keys=True, indent=2)) diff --git a/tests/test_reportlab.py b/tests/test_reportlab.py index 8fd40ee..d3b589b 100644 --- a/tests/test_reportlab.py +++ b/tests/test_reportlab.py @@ -1,5 +1,6 @@ #!/usr/bin/env python -# -*- coding: utf-8 -*- + +from __future__ import annotations import os import sys diff --git a/tests/testlive_comprehensive.py b/tests/testlive_comprehensive.py index 6aab0ec..852d7a3 100644 --- a/tests/testlive_comprehensive.py +++ b/tests/testlive_comprehensive.py @@ -1,5 +1,7 @@ #!/usr/bin/env python3 +from __future__ import annotations + import os import sys diff --git a/tests/testlive_sync.py b/tests/testlive_sync.py index 768ba31..bad65a2 100644 --- a/tests/testlive_sync.py +++ b/tests/testlive_sync.py @@ -1,5 +1,7 @@ #!/usr/bin/env python3 +from __future__ import annotations + import time import sys import unittest From f11681af528f147ca6939706a085e833ab7dded3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Vinot?= Date: Wed, 17 Jan 2024 13:38:00 +0100 Subject: [PATCH 40/80] fix: Python < 3.10 support on typing --- pymisp/api.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pymisp/api.py b/pymisp/api.py index eaadb99..80872f3 100644 --- a/pymisp/api.py +++ b/pymisp/api.py @@ -1,6 +1,6 @@ from __future__ import annotations -from typing import TypeVar, Any, Mapping, Iterable, MutableMapping +from typing import TypeVar, Any, Mapping, Iterable, MutableMapping, Union from datetime import date, datetime import csv from pathlib import Path @@ -57,7 +57,7 @@ except ImportError: SearchType = TypeVar('SearchType', str, int) # str: string to search / list: values to search (OR) / dict: {'OR': [list], 'NOT': [list], 'AND': [list]} -SearchParameterTypes = TypeVar('SearchParameterTypes', str, list[str | int], dict[str, str | int]) +SearchParameterTypes = TypeVar('SearchParameterTypes', str, list[Union[str, int]], dict[str, Union[str, int]]) ToIDSType = TypeVar('ToIDSType', str, int, bool) From a298245fd2a6004ef00d151a2df9c50cc5185356 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Vinot?= Date: Wed, 17 Jan 2024 13:40:10 +0100 Subject: [PATCH 41/80] fix: Python < 3.10 support on typing, for good. --- pymisp/api.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pymisp/api.py b/pymisp/api.py index 80872f3..b1f6e55 100644 --- a/pymisp/api.py +++ b/pymisp/api.py @@ -1,6 +1,6 @@ from __future__ import annotations -from typing import TypeVar, Any, Mapping, Iterable, MutableMapping, Union +from typing import TypeVar, Any, Mapping, Iterable, MutableMapping, Union, List, Dict from datetime import date, datetime import csv from pathlib import Path @@ -57,7 +57,7 @@ except ImportError: SearchType = TypeVar('SearchType', str, int) # str: string to search / list: values to search (OR) / dict: {'OR': [list], 'NOT': [list], 'AND': [list]} -SearchParameterTypes = TypeVar('SearchParameterTypes', str, list[Union[str, int]], dict[str, Union[str, int]]) +SearchParameterTypes = TypeVar('SearchParameterTypes', str, List[Union[str, int]], Dict[str, Union[str, int]]) ToIDSType = TypeVar('ToIDSType', str, int, bool) From d4b068965c021acd0c5dfa808dd88f686f9bd9fa Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 18 Jan 2024 16:33:38 +0000 Subject: [PATCH 42/80] build(deps-dev): bump jupyter-lsp from 2.2.1 to 2.2.2 Bumps [jupyter-lsp](https://github.com/jupyter-lsp/jupyterlab-lsp) from 2.2.1 to 2.2.2. - [Release notes](https://github.com/jupyter-lsp/jupyterlab-lsp/releases) - [Changelog](https://github.com/jupyter-lsp/jupyterlab-lsp/blob/main/CHANGELOG.md) - [Commits](https://github.com/jupyter-lsp/jupyterlab-lsp/commits) --- updated-dependencies: - dependency-name: jupyter-lsp dependency-type: indirect ... Signed-off-by: dependabot[bot] --- poetry.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/poetry.lock b/poetry.lock index 9620789..787361a 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1349,13 +1349,13 @@ test = ["click", "pre-commit", "pytest (>=7.0)", "pytest-asyncio (>=0.19.0)", "p [[package]] name = "jupyter-lsp" -version = "2.2.1" +version = "2.2.2" description = "Multi-Language Server WebSocket proxy for Jupyter Notebook/Lab server" optional = false python-versions = ">=3.8" files = [ - {file = "jupyter-lsp-2.2.1.tar.gz", hash = "sha256:b17fab6d70fe83c8896b0cff59237640038247c196056b43684a0902b6a9e0fb"}, - {file = "jupyter_lsp-2.2.1-py3-none-any.whl", hash = "sha256:17a689910c5e4ae5e7d334b02f31d08ffbe98108f6f658fb05e4304b4345368b"}, + {file = "jupyter-lsp-2.2.2.tar.gz", hash = "sha256:256d24620542ae4bba04a50fc1f6ffe208093a07d8e697fea0a8d1b8ca1b7e5b"}, + {file = "jupyter_lsp-2.2.2-py3-none-any.whl", hash = "sha256:3b95229e4168355a8c91928057c1621ac3510ba98b2a925e82ebd77f078b1aa5"}, ] [package.dependencies] From be0b551d8ba0823760abc482c12613bb2982601f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Vinot?= Date: Fri, 19 Jan 2024 11:05:31 +0100 Subject: [PATCH 43/80] chg: Bump deps --- poetry.lock | 311 ++++++++++++++++++++++++------------------------- pyproject.toml | 2 +- 2 files changed, 153 insertions(+), 160 deletions(-) diff --git a/poetry.lock b/poetry.lock index 9620789..1bc7019 100644 --- a/poetry.lock +++ b/poetry.lock @@ -240,19 +240,22 @@ tzdata = ["tzdata"] [[package]] name = "beautifulsoup4" -version = "4.12.2" +version = "4.12.3" description = "Screen-scraping library" optional = false python-versions = ">=3.6.0" files = [ - {file = "beautifulsoup4-4.12.2-py3-none-any.whl", hash = "sha256:bd2520ca0d9d7d12694a53d44ac482d181b4ec1888909b035a3dbf40d0f57d4a"}, - {file = "beautifulsoup4-4.12.2.tar.gz", hash = "sha256:492bbc69dca35d12daac71c4db1bfff0c876c00ef4a2ffacce226d4638eb72da"}, + {file = "beautifulsoup4-4.12.3-py3-none-any.whl", hash = "sha256:b80878c9f40111313e55da8ba20bdba06d8fa3969fc68304167741bbf9e082ed"}, + {file = "beautifulsoup4-4.12.3.tar.gz", hash = "sha256:74e3d1928edc070d21748185c46e3fb33490f22f52a3addee9aee0f4f7781051"}, ] [package.dependencies] soupsieve = ">1.2" [package.extras] +cchardet = ["cchardet"] +chardet = ["chardet"] +charset-normalizer = ["charset-normalizer"] html5lib = ["html5lib"] lxml = ["lxml"] @@ -1015,13 +1018,13 @@ files = [ [[package]] name = "ipykernel" -version = "6.28.0" +version = "6.29.0" description = "IPython Kernel for Jupyter" optional = false python-versions = ">=3.8" files = [ - {file = "ipykernel-6.28.0-py3-none-any.whl", hash = "sha256:c6e9a9c63a7f4095c0a22a79f765f079f9ec7be4f2430a898ddea889e8665661"}, - {file = "ipykernel-6.28.0.tar.gz", hash = "sha256:69c11403d26de69df02225916f916b37ea4b9af417da0a8c827f84328d88e5f3"}, + {file = "ipykernel-6.29.0-py3-none-any.whl", hash = "sha256:076663ca68492576f051e4af7720d33f34383e655f2be0d544c8b1c9de915b2f"}, + {file = "ipykernel-6.29.0.tar.gz", hash = "sha256:b5dd3013cab7b330df712891c96cd1ab868c27a7159e606f762015e9bf8ceb3f"}, ] [package.dependencies] @@ -1044,7 +1047,7 @@ cov = ["coverage[toml]", "curio", "matplotlib", "pytest-cov", "trio"] docs = ["myst-parser", "pydata-sphinx-theme", "sphinx", "sphinx-autodoc-typehints", "sphinxcontrib-github-alt", "sphinxcontrib-spelling", "trio"] pyqt5 = ["pyqt5"] pyside6 = ["pyside6"] -test = ["flaky", "ipyparallel", "pre-commit", "pytest (>=7.0)", "pytest-asyncio", "pytest-cov", "pytest-timeout"] +test = ["flaky", "ipyparallel", "pre-commit", "pytest (>=7.0)", "pytest-asyncio (==0.23.2)", "pytest-cov", "pytest-timeout"] [[package]] name = "ipython" @@ -1235,13 +1238,13 @@ files = [ [[package]] name = "jsonschema" -version = "4.20.0" +version = "4.21.0" description = "An implementation of JSON Schema validation for Python" optional = false python-versions = ">=3.8" files = [ - {file = "jsonschema-4.20.0-py3-none-any.whl", hash = "sha256:ed6231f0429ecf966f5bc8dfef245998220549cbbcf140f913b7464c52c3b6b3"}, - {file = "jsonschema-4.20.0.tar.gz", hash = "sha256:4f614fd46d8d61258610998997743ec5492a648b33cf478c1ddc23ed4598a5fa"}, + {file = "jsonschema-4.21.0-py3-none-any.whl", hash = "sha256:70a09719d375c0a2874571b363c8a24be7df8071b80c9aa76bc4551e7297c63c"}, + {file = "jsonschema-4.21.0.tar.gz", hash = "sha256:3ba18e27f7491ea4a1b22edce00fb820eec968d397feb3f9cb61d5894bb38167"}, ] [package.dependencies] @@ -1349,13 +1352,13 @@ test = ["click", "pre-commit", "pytest (>=7.0)", "pytest-asyncio (>=0.19.0)", "p [[package]] name = "jupyter-lsp" -version = "2.2.1" +version = "2.2.2" description = "Multi-Language Server WebSocket proxy for Jupyter Notebook/Lab server" optional = false python-versions = ">=3.8" files = [ - {file = "jupyter-lsp-2.2.1.tar.gz", hash = "sha256:b17fab6d70fe83c8896b0cff59237640038247c196056b43684a0902b6a9e0fb"}, - {file = "jupyter_lsp-2.2.1-py3-none-any.whl", hash = "sha256:17a689910c5e4ae5e7d334b02f31d08ffbe98108f6f658fb05e4304b4345368b"}, + {file = "jupyter-lsp-2.2.2.tar.gz", hash = "sha256:256d24620542ae4bba04a50fc1f6ffe208093a07d8e697fea0a8d1b8ca1b7e5b"}, + {file = "jupyter_lsp-2.2.2-py3-none-any.whl", hash = "sha256:3b95229e4168355a8c91928057c1621ac3510ba98b2a925e82ebd77f078b1aa5"}, ] [package.dependencies] @@ -1364,13 +1367,13 @@ jupyter-server = ">=1.1.2" [[package]] name = "jupyter-server" -version = "2.12.4" +version = "2.12.5" description = "The backend—i.e. core services, APIs, and REST endpoints—to Jupyter web applications." optional = false python-versions = ">=3.8" files = [ - {file = "jupyter_server-2.12.4-py3-none-any.whl", hash = "sha256:a125ae18a60de568f78f55c84dd58759901a18ef279abf0418ac220653ca1320"}, - {file = "jupyter_server-2.12.4.tar.gz", hash = "sha256:41f4a1e6b912cc24a7c6c694851b37d3d8412b180f43d72315fe422cb2b85cc2"}, + {file = "jupyter_server-2.12.5-py3-none-any.whl", hash = "sha256:184a0f82809a8522777cfb6b760ab6f4b1bb398664c5860a27cec696cb884923"}, + {file = "jupyter_server-2.12.5.tar.gz", hash = "sha256:0edb626c94baa22809be1323f9770cf1c00a952b17097592e40d03e6a3951689"}, ] [package.dependencies] @@ -1632,13 +1635,13 @@ files = [ [[package]] name = "msoffcrypto-tool" -version = "5.2.0" +version = "5.3.1" description = "Python tool and library for decrypting MS Office files with passwords or other keys" optional = true python-versions = ">=3.8,<4.0" files = [ - {file = "msoffcrypto_tool-5.2.0-py3-none-any.whl", hash = "sha256:2c6c1040df7a4f8e08256f9562f7898d49ec99ae7a6525f9725681b799b8af70"}, - {file = "msoffcrypto_tool-5.2.0.tar.gz", hash = "sha256:2f334cecd19eaa7426f26fc6f661a30268d4817e48d4c006708b4b29dcab6d7f"}, + {file = "msoffcrypto_tool-5.3.1-py3-none-any.whl", hash = "sha256:4e44c10e38ca06d0ea511a31ee8834bfdedaf304b1369a0d3919db4f495dd5e4"}, + {file = "msoffcrypto_tool-5.3.1.tar.gz", hash = "sha256:f800ff133b9a753dfedff6a37b0f79bfeb8cc6856487b91dd486110c7d4f4099"}, ] [package.dependencies] @@ -1727,13 +1730,13 @@ test = ["flaky", "ipykernel (>=6.19.3)", "ipython", "ipywidgets", "nbconvert (>= [[package]] name = "nbconvert" -version = "7.14.1" +version = "7.14.2" description = "Converting Jupyter Notebooks" optional = false python-versions = ">=3.8" files = [ - {file = "nbconvert-7.14.1-py3-none-any.whl", hash = "sha256:aa83e3dd27ea38d0c1d908e3ce9518d15fa908dd30521b6d5040bd23f33fffb0"}, - {file = "nbconvert-7.14.1.tar.gz", hash = "sha256:20cba10e0448dc76b3bebfe1adf923663e3b98338daf77b97b42511ef5a88618"}, + {file = "nbconvert-7.14.2-py3-none-any.whl", hash = "sha256:db28590cef90f7faf2ebbc71acd402cbecf13d29176df728c0a9025a49345ea1"}, + {file = "nbconvert-7.14.2.tar.gz", hash = "sha256:a7f8808fd4e082431673ac538400218dd45efd076fbeb07cc6e5aa5a3a4e949e"}, ] [package.dependencies] @@ -1786,13 +1789,13 @@ test = ["pep440", "pre-commit", "pytest", "testpath"] [[package]] name = "nest-asyncio" -version = "1.5.8" +version = "1.5.9" description = "Patch asyncio to allow nested event loops" optional = false python-versions = ">=3.5" files = [ - {file = "nest_asyncio-1.5.8-py3-none-any.whl", hash = "sha256:accda7a339a70599cb08f9dd09a67e0c2ef8d8d6f4c07f96ab203f2ae254e48d"}, - {file = "nest_asyncio-1.5.8.tar.gz", hash = "sha256:25aa2ca0d2a5b5531956b9e273b45cf664cae2b145101d73b86b199978d48fdb"}, + {file = "nest_asyncio-1.5.9-py3-none-any.whl", hash = "sha256:61ec07ef052e72e3de22045b81b2cc7d71fceb04c568ba0b2e4b2f9f5231bec2"}, + {file = "nest_asyncio-1.5.9.tar.gz", hash = "sha256:d1e1144e9c6e3e6392e0fcf5211cb1c8374b5648a98f1ebe48e5336006b41907"}, ] [[package]] @@ -1872,13 +1875,13 @@ files = [ [[package]] name = "pandocfilters" -version = "1.5.0" +version = "1.5.1" description = "Utilities for writing pandoc filters in python" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" files = [ - {file = "pandocfilters-1.5.0-py2.py3-none-any.whl", hash = "sha256:33aae3f25fd1a026079f5d27bdd52496f0e0803b3469282162bafdcbdf6ef14f"}, - {file = "pandocfilters-1.5.0.tar.gz", hash = "sha256:0b679503337d233b4339a817bfc8c50064e2eff681314376a47cb582305a7a38"}, + {file = "pandocfilters-1.5.1-py2.py3-none-any.whl", hash = "sha256:93be382804a9cdb0a7267585f157e5d1731bbe5545a85b268d6f5fe6232de2bc"}, + {file = "pandocfilters-1.5.1.tar.gz", hash = "sha256:002b4a555ee4ebc03f8b66307e287fa492e4a77b4ea14d3f934328297bb4939e"}, ] [[package]] @@ -2647,110 +2650,110 @@ files = [ [[package]] name = "rpds-py" -version = "0.16.2" +version = "0.17.1" description = "Python bindings to Rust's persistent data structures (rpds)" optional = false python-versions = ">=3.8" files = [ - {file = "rpds_py-0.16.2-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:509b617ac787cd1149600e731db9274ebbef094503ca25158e6f23edaba1ca8f"}, - {file = "rpds_py-0.16.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:413b9c17388bbd0d87a329d8e30c1a4c6e44e2bb25457f43725a8e6fe4161e9e"}, - {file = "rpds_py-0.16.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2946b120718eba9af2b4dd103affc1164a87b9e9ebff8c3e4c05d7b7a7e274e2"}, - {file = "rpds_py-0.16.2-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:35ae5ece284cf36464eb160880018cf6088a9ac5ddc72292a6092b6ef3f4da53"}, - {file = "rpds_py-0.16.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3dc6a7620ba7639a3db6213da61312cb4aa9ac0ca6e00dc1cbbdc21c2aa6eb57"}, - {file = "rpds_py-0.16.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8cb6fe8ecdfffa0e711a75c931fb39f4ba382b4b3ccedeca43f18693864fe850"}, - {file = "rpds_py-0.16.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6dace7b26a13353e24613417ce2239491b40a6ad44e5776a18eaff7733488b44"}, - {file = "rpds_py-0.16.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1bdbc5fcb04a7309074de6b67fa9bc4b418ab3fc435fec1f2779a0eced688d04"}, - {file = "rpds_py-0.16.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:f42e25c016927e2a6b1ce748112c3ab134261fc2ddc867e92d02006103e1b1b7"}, - {file = "rpds_py-0.16.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:eab36eae3f3e8e24b05748ec9acc66286662f5d25c52ad70cadab544e034536b"}, - {file = "rpds_py-0.16.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:0474df4ade9a3b4af96c3d36eb81856cb9462e4c6657d4caecfd840d2a13f3c9"}, - {file = "rpds_py-0.16.2-cp310-none-win32.whl", hash = "sha256:84c5a4d1f9dd7e2d2c44097fb09fffe728629bad31eb56caf97719e55575aa82"}, - {file = "rpds_py-0.16.2-cp310-none-win_amd64.whl", hash = "sha256:2bd82db36cd70b3628c0c57d81d2438e8dd4b7b32a6a9f25f24ab0e657cb6c4e"}, - {file = "rpds_py-0.16.2-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:adc0c3d6fc6ae35fee3e4917628983f6ce630d513cbaad575b4517d47e81b4bb"}, - {file = "rpds_py-0.16.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ec23fcad480e77ede06cf4127a25fc440f7489922e17fc058f426b5256ee0edb"}, - {file = "rpds_py-0.16.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:07aab64e2808c3ebac2a44f67e9dc0543812b715126dfd6fe4264df527556cb6"}, - {file = "rpds_py-0.16.2-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a4ebb8b20bd09c5ce7884c8f0388801100f5e75e7f733b1b6613c713371feefc"}, - {file = "rpds_py-0.16.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a3d7e2ea25d3517c6d7e5a1cc3702cffa6bd18d9ef8d08d9af6717fc1c700eed"}, - {file = "rpds_py-0.16.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f28ac0e8e7242d140f99402a903a2c596ab71550272ae9247ad78f9a932b5698"}, - {file = "rpds_py-0.16.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:19f00f57fdd38db4bb5ad09f9ead1b535332dbf624200e9029a45f1f35527ebb"}, - {file = "rpds_py-0.16.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:3da5a4c56953bdbf6d04447c3410309616c54433146ccdb4a277b9cb499bc10e"}, - {file = "rpds_py-0.16.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:ec2e1cf025b2c0f48ec17ff3e642661da7ee332d326f2e6619366ce8e221f018"}, - {file = "rpds_py-0.16.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:e0441fb4fdd39a230477b2ca9be90868af64425bfe7b122b57e61e45737a653b"}, - {file = "rpds_py-0.16.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:9f0350ef2fba5f34eb0c9000ea328e51b9572b403d2f7f3b19f24085f6f598e8"}, - {file = "rpds_py-0.16.2-cp311-none-win32.whl", hash = "sha256:5a80e2f83391ad0808b4646732af2a7b67550b98f0cae056cb3b40622a83dbb3"}, - {file = "rpds_py-0.16.2-cp311-none-win_amd64.whl", hash = "sha256:e04e56b4ca7a770593633556e8e9e46579d66ec2ada846b401252a2bdcf70a6d"}, - {file = "rpds_py-0.16.2-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:5e6caa3809e50690bd92fa490f5c38caa86082c8c3315aa438bce43786d5e90d"}, - {file = "rpds_py-0.16.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2e53b9b25cac9065328901713a7e9e3b12e4f57ef4280b370fbbf6fef2052eef"}, - {file = "rpds_py-0.16.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:af27423662f32d7501a00c5e7342f7dbd1e4a718aea7a239781357d15d437133"}, - {file = "rpds_py-0.16.2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:43d4dd5fb16eb3825742bad8339d454054261ab59fed2fbac84e1d84d5aae7ba"}, - {file = "rpds_py-0.16.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e061de3b745fe611e23cd7318aec2c8b0e4153939c25c9202a5811ca911fd733"}, - {file = "rpds_py-0.16.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3b811d182ad17ea294f2ec63c0621e7be92a1141e1012383461872cead87468f"}, - {file = "rpds_py-0.16.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5552f328eaef1a75ff129d4d0c437bf44e43f9436d3996e8eab623ea0f5fcf73"}, - {file = "rpds_py-0.16.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:dcbe1f8dd179e4d69b70b1f1d9bb6fd1e7e1bdc9c9aad345cdeb332e29d40748"}, - {file = "rpds_py-0.16.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8aad80645a011abae487d356e0ceb359f4938dfb6f7bcc410027ed7ae4f7bb8b"}, - {file = "rpds_py-0.16.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:b6f5549d6ed1da9bfe3631ca9483ae906f21410be2445b73443fa9f017601c6f"}, - {file = "rpds_py-0.16.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:d452817e0d9c749c431a1121d56a777bd7099b720b3d1c820f1725cb40928f58"}, - {file = "rpds_py-0.16.2-cp312-none-win32.whl", hash = "sha256:888a97002e986eca10d8546e3c8b97da1d47ad8b69726dcfeb3e56348ebb28a3"}, - {file = "rpds_py-0.16.2-cp312-none-win_amd64.whl", hash = "sha256:d8dda2a806dfa4a9b795950c4f5cc56d6d6159f7d68080aedaff3bdc9b5032f5"}, - {file = "rpds_py-0.16.2-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:071980663c273bf3d388fe5c794c547e6f35ba3335477072c713a3176bf14a60"}, - {file = "rpds_py-0.16.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:726ac36e8a3bb8daef2fd482534cabc5e17334052447008405daca7ca04a3108"}, - {file = "rpds_py-0.16.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e9e557db6a177470316c82f023e5d571811c9a4422b5ea084c85da9aa3c035fc"}, - {file = "rpds_py-0.16.2-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:90123853fc8b1747f80b0d354be3d122b4365a93e50fc3aacc9fb4c2488845d6"}, - {file = "rpds_py-0.16.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a61f659665a39a4d17d699ab3593d7116d66e1e2e3f03ef3fb8f484e91908808"}, - {file = "rpds_py-0.16.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cc97f0640e91d7776530f06e6836c546c1c752a52de158720c4224c9e8053cad"}, - {file = "rpds_py-0.16.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:44a54e99a2b9693a37ebf245937fd6e9228b4cbd64b9cc961e1f3391ec6c7391"}, - {file = "rpds_py-0.16.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:bd4b677d929cf1f6bac07ad76e0f2d5de367e6373351c01a9c0a39f6b21b4a8b"}, - {file = "rpds_py-0.16.2-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:5ef00873303d678aaf8b0627e111fd434925ca01c657dbb2641410f1cdaef261"}, - {file = "rpds_py-0.16.2-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:349cb40897fd529ca15317c22c0eab67f5ac5178b5bd2c6adc86172045210acc"}, - {file = "rpds_py-0.16.2-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:2ddef620e70eaffebed5932ce754d539c0930f676aae6212f8e16cd9743dd365"}, - {file = "rpds_py-0.16.2-cp38-none-win32.whl", hash = "sha256:882ce6e25e585949c3d9f9abd29202367175e0aab3aba0c58c9abbb37d4982ff"}, - {file = "rpds_py-0.16.2-cp38-none-win_amd64.whl", hash = "sha256:f4bd4578e44f26997e9e56c96dedc5f1af43cc9d16c4daa29c771a00b2a26851"}, - {file = "rpds_py-0.16.2-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:69ac7ea9897ec201ce68b48582f3eb34a3f9924488a5432a93f177bf76a82a7e"}, - {file = "rpds_py-0.16.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a9880b4656efe36ccad41edc66789e191e5ee19a1ea8811e0aed6f69851a82f4"}, - {file = "rpds_py-0.16.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ee94cb58c0ba2c62ee108c2b7c9131b2c66a29e82746e8fa3aa1a1effbd3dcf1"}, - {file = "rpds_py-0.16.2-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:24f7a2eb3866a9e91f4599851e0c8d39878a470044875c49bd528d2b9b88361c"}, - {file = "rpds_py-0.16.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ca57468da2d9a660bcf8961637c85f2fbb2aa64d9bc3f9484e30c3f9f67b1dd7"}, - {file = "rpds_py-0.16.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ccd4e400309e1f34a5095bf9249d371f0fd60f8a3a5c4a791cad7b99ce1fd38d"}, - {file = "rpds_py-0.16.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80443fe2f7b3ea3934c5d75fb0e04a5dbb4a8e943e5ff2de0dec059202b70a8b"}, - {file = "rpds_py-0.16.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4d6a9f052e72d493efd92a77f861e45bab2f6be63e37fa8ecf0c6fd1a58fedb0"}, - {file = "rpds_py-0.16.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:35953f4f2b3216421af86fd236b7c0c65935936a94ea83ddbd4904ba60757773"}, - {file = "rpds_py-0.16.2-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:981d135c7cdaf6cd8eadae1c950de43b976de8f09d8e800feed307140d3d6d00"}, - {file = "rpds_py-0.16.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:d0dd7ed2f16df2e129496e7fbe59a34bc2d7fc8db443a606644d069eb69cbd45"}, - {file = "rpds_py-0.16.2-cp39-none-win32.whl", hash = "sha256:703d95c75a72e902544fda08e965885525e297578317989fd15a6ce58414b41d"}, - {file = "rpds_py-0.16.2-cp39-none-win_amd64.whl", hash = "sha256:e93ec1b300acf89730cf27975ef574396bc04edecc358e9bd116fb387a123239"}, - {file = "rpds_py-0.16.2-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:44627b6ca7308680a70766454db5249105fa6344853af6762eaad4158a2feebe"}, - {file = "rpds_py-0.16.2-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:3f91df8e6dbb7360e176d1affd5fb0246d2b88d16aa5ebc7db94fd66b68b61da"}, - {file = "rpds_py-0.16.2-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6d904c5693e08bad240f16d79305edba78276be87061c872a4a15e2c301fa2c0"}, - {file = "rpds_py-0.16.2-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:290a81cfbe4673285cdf140ec5cd1658ffbf63ab359f2b352ebe172e7cfa5bf0"}, - {file = "rpds_py-0.16.2-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b634c5ec0103c5cbebc24ebac4872b045cccb9456fc59efdcf6fe39775365bd2"}, - {file = "rpds_py-0.16.2-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a297a4d08cc67c7466c873c78039d87840fb50d05473db0ec1b7b03d179bf322"}, - {file = "rpds_py-0.16.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b2e75e17bd0bb66ee34a707da677e47c14ee51ccef78ed6a263a4cc965a072a1"}, - {file = "rpds_py-0.16.2-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f1b9d9260e06ea017feb7172976ab261e011c1dc2f8883c7c274f6b2aabfe01a"}, - {file = "rpds_py-0.16.2-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:162d7cd9cd311c1b0ff1c55a024b8f38bd8aad1876b648821da08adc40e95734"}, - {file = "rpds_py-0.16.2-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:9b32f742ce5b57201305f19c2ef7a184b52f6f9ba6871cc042c2a61f0d6b49b8"}, - {file = "rpds_py-0.16.2-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:ac08472f41ea77cd6a5dae36ae7d4ed3951d6602833af87532b556c1b4601d63"}, - {file = "rpds_py-0.16.2-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:495a14b72bbe217f2695dcd9b5ab14d4f8066a00f5d209ed94f0aca307f85f6e"}, - {file = "rpds_py-0.16.2-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:8d6b6937ae9eac6d6c0ca3c42774d89fa311f55adff3970fb364b34abde6ed3d"}, - {file = "rpds_py-0.16.2-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6a61226465bda9283686db8f17d02569a98e4b13c637be5a26d44aa1f1e361c2"}, - {file = "rpds_py-0.16.2-pp38-pypy38_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5cf6af100ffb5c195beec11ffaa8cf8523057f123afa2944e6571d54da84cdc9"}, - {file = "rpds_py-0.16.2-pp38-pypy38_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6df15846ee3fb2e6397fe25d7ca6624af9f89587f3f259d177b556fed6bebe2c"}, - {file = "rpds_py-0.16.2-pp38-pypy38_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1be2f033df1b8be8c3167ba3c29d5dca425592ee31e35eac52050623afba5772"}, - {file = "rpds_py-0.16.2-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:96f957d6ab25a78b9e7fc9749d754b98eac825a112b4e666525ce89afcbd9ed5"}, - {file = "rpds_py-0.16.2-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:088396c7c70e59872f67462fcac3ecbded5233385797021976a09ebd55961dfe"}, - {file = "rpds_py-0.16.2-pp38-pypy38_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:4c46ad6356e1561f2a54f08367d1d2e70a0a1bb2db2282d2c1972c1d38eafc3b"}, - {file = "rpds_py-0.16.2-pp38-pypy38_pp73-musllinux_1_2_i686.whl", hash = "sha256:47713dc4fce213f5c74ca8a1f6a59b622fc1b90868deb8e8e4d993e421b4b39d"}, - {file = "rpds_py-0.16.2-pp38-pypy38_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:f811771019f063bbd0aa7bb72c8a934bc13ebacb4672d712fc1639cfd314cccc"}, - {file = "rpds_py-0.16.2-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:f19afcfc0dd0dca35694df441e9b0f95bc231b512f51bded3c3d8ca32153ec19"}, - {file = "rpds_py-0.16.2-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:a4b682c5775d6a3d21e314c10124599976809455ee67020e8e72df1769b87bc3"}, - {file = "rpds_py-0.16.2-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c647ca87fc0ebe808a41de912e9a1bfef9acb85257e5d63691364ac16b81c1f0"}, - {file = "rpds_py-0.16.2-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:302bd4983bbd47063e452c38be66153760112f6d3635c7eeefc094299fa400a9"}, - {file = "rpds_py-0.16.2-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bf721ede3eb7b829e4a9b8142bd55db0bdc82902720548a703f7e601ee13bdc3"}, - {file = "rpds_py-0.16.2-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:358dafc89ce3894c7f486c615ba914609f38277ef67f566abc4c854d23b997fa"}, - {file = "rpds_py-0.16.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cad0f59ee3dc35526039f4bc23642d52d5f6616b5f687d846bfc6d0d6d486db0"}, - {file = "rpds_py-0.16.2-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:cffa76b385dfe1e38527662a302b19ffb0e7f5cf7dd5e89186d2c94a22dd9d0c"}, - {file = "rpds_py-0.16.2-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:83640a5d7cd3bff694747d50436b8b541b5b9b9782b0c8c1688931d6ee1a1f2d"}, - {file = "rpds_py-0.16.2-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:ed99b4f7179d2111702020fd7d156e88acd533f5a7d3971353e568b6051d5c97"}, - {file = "rpds_py-0.16.2-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:4022b9dc620e14f30201a8a73898a873c8e910cb642bcd2f3411123bc527f6ac"}, - {file = "rpds_py-0.16.2.tar.gz", hash = "sha256:781ef8bfc091b19960fc0142a23aedadafa826bc32b433fdfe6fd7f964d7ef44"}, + {file = "rpds_py-0.17.1-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:4128980a14ed805e1b91a7ed551250282a8ddf8201a4e9f8f5b7e6225f54170d"}, + {file = "rpds_py-0.17.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ff1dcb8e8bc2261a088821b2595ef031c91d499a0c1b031c152d43fe0a6ecec8"}, + {file = "rpds_py-0.17.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d65e6b4f1443048eb7e833c2accb4fa7ee67cc7d54f31b4f0555b474758bee55"}, + {file = "rpds_py-0.17.1-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a71169d505af63bb4d20d23a8fbd4c6ce272e7bce6cc31f617152aa784436f29"}, + {file = "rpds_py-0.17.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:436474f17733c7dca0fbf096d36ae65277e8645039df12a0fa52445ca494729d"}, + {file = "rpds_py-0.17.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:10162fe3f5f47c37ebf6d8ff5a2368508fe22007e3077bf25b9c7d803454d921"}, + {file = "rpds_py-0.17.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:720215373a280f78a1814becb1312d4e4d1077b1202a56d2b0815e95ccb99ce9"}, + {file = "rpds_py-0.17.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:70fcc6c2906cfa5c6a552ba7ae2ce64b6c32f437d8f3f8eea49925b278a61453"}, + {file = "rpds_py-0.17.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:91e5a8200e65aaac342a791272c564dffcf1281abd635d304d6c4e6b495f29dc"}, + {file = "rpds_py-0.17.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:99f567dae93e10be2daaa896e07513dd4bf9c2ecf0576e0533ac36ba3b1d5394"}, + {file = "rpds_py-0.17.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:24e4900a6643f87058a27320f81336d527ccfe503984528edde4bb660c8c8d59"}, + {file = "rpds_py-0.17.1-cp310-none-win32.whl", hash = "sha256:0bfb09bf41fe7c51413f563373e5f537eaa653d7adc4830399d4e9bdc199959d"}, + {file = "rpds_py-0.17.1-cp310-none-win_amd64.whl", hash = "sha256:20de7b7179e2031a04042e85dc463a93a82bc177eeba5ddd13ff746325558aa6"}, + {file = "rpds_py-0.17.1-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:65dcf105c1943cba45d19207ef51b8bc46d232a381e94dd38719d52d3980015b"}, + {file = "rpds_py-0.17.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:01f58a7306b64e0a4fe042047dd2b7d411ee82e54240284bab63e325762c1147"}, + {file = "rpds_py-0.17.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:071bc28c589b86bc6351a339114fb7a029f5cddbaca34103aa573eba7b482382"}, + {file = "rpds_py-0.17.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ae35e8e6801c5ab071b992cb2da958eee76340e6926ec693b5ff7d6381441745"}, + {file = "rpds_py-0.17.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:149c5cd24f729e3567b56e1795f74577aa3126c14c11e457bec1b1c90d212e38"}, + {file = "rpds_py-0.17.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e796051f2070f47230c745d0a77a91088fbee2cc0502e9b796b9c6471983718c"}, + {file = "rpds_py-0.17.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:60e820ee1004327609b28db8307acc27f5f2e9a0b185b2064c5f23e815f248f8"}, + {file = "rpds_py-0.17.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1957a2ab607f9added64478a6982742eb29f109d89d065fa44e01691a20fc20a"}, + {file = "rpds_py-0.17.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8587fd64c2a91c33cdc39d0cebdaf30e79491cc029a37fcd458ba863f8815383"}, + {file = "rpds_py-0.17.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:4dc889a9d8a34758d0fcc9ac86adb97bab3fb7f0c4d29794357eb147536483fd"}, + {file = "rpds_py-0.17.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:2953937f83820376b5979318840f3ee47477d94c17b940fe31d9458d79ae7eea"}, + {file = "rpds_py-0.17.1-cp311-none-win32.whl", hash = "sha256:1bfcad3109c1e5ba3cbe2f421614e70439f72897515a96c462ea657261b96518"}, + {file = "rpds_py-0.17.1-cp311-none-win_amd64.whl", hash = "sha256:99da0a4686ada4ed0f778120a0ea8d066de1a0a92ab0d13ae68492a437db78bf"}, + {file = "rpds_py-0.17.1-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:1dc29db3900cb1bb40353772417800f29c3d078dbc8024fd64655a04ee3c4bdf"}, + {file = "rpds_py-0.17.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:82ada4a8ed9e82e443fcef87e22a3eed3654dd3adf6e3b3a0deb70f03e86142a"}, + {file = "rpds_py-0.17.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1d36b2b59e8cc6e576f8f7b671e32f2ff43153f0ad6d0201250a7c07f25d570e"}, + {file = "rpds_py-0.17.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3677fcca7fb728c86a78660c7fb1b07b69b281964673f486ae72860e13f512ad"}, + {file = "rpds_py-0.17.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:516fb8c77805159e97a689e2f1c80655c7658f5af601c34ffdb916605598cda2"}, + {file = "rpds_py-0.17.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:df3b6f45ba4515632c5064e35ca7f31d51d13d1479673185ba8f9fefbbed58b9"}, + {file = "rpds_py-0.17.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a967dd6afda7715d911c25a6ba1517975acd8d1092b2f326718725461a3d33f9"}, + {file = "rpds_py-0.17.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:dbbb95e6fc91ea3102505d111b327004d1c4ce98d56a4a02e82cd451f9f57140"}, + {file = "rpds_py-0.17.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:02866e060219514940342a1f84303a1ef7a1dad0ac311792fbbe19b521b489d2"}, + {file = "rpds_py-0.17.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:2528ff96d09f12e638695f3a2e0c609c7b84c6df7c5ae9bfeb9252b6fa686253"}, + {file = "rpds_py-0.17.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:bd345a13ce06e94c753dab52f8e71e5252aec1e4f8022d24d56decd31e1b9b23"}, + {file = "rpds_py-0.17.1-cp312-none-win32.whl", hash = "sha256:2a792b2e1d3038daa83fa474d559acfd6dc1e3650ee93b2662ddc17dbff20ad1"}, + {file = "rpds_py-0.17.1-cp312-none-win_amd64.whl", hash = "sha256:292f7344a3301802e7c25c53792fae7d1593cb0e50964e7bcdcc5cf533d634e3"}, + {file = "rpds_py-0.17.1-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:8ffe53e1d8ef2520ebcf0c9fec15bb721da59e8ef283b6ff3079613b1e30513d"}, + {file = "rpds_py-0.17.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:4341bd7579611cf50e7b20bb8c2e23512a3dc79de987a1f411cb458ab670eb90"}, + {file = "rpds_py-0.17.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2f4eb548daf4836e3b2c662033bfbfc551db58d30fd8fe660314f86bf8510b93"}, + {file = "rpds_py-0.17.1-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b686f25377f9c006acbac63f61614416a6317133ab7fafe5de5f7dc8a06d42eb"}, + {file = "rpds_py-0.17.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4e21b76075c01d65d0f0f34302b5a7457d95721d5e0667aea65e5bb3ab415c25"}, + {file = "rpds_py-0.17.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b86b21b348f7e5485fae740d845c65a880f5d1eda1e063bc59bef92d1f7d0c55"}, + {file = "rpds_py-0.17.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f175e95a197f6a4059b50757a3dca33b32b61691bdbd22c29e8a8d21d3914cae"}, + {file = "rpds_py-0.17.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1701fc54460ae2e5efc1dd6350eafd7a760f516df8dbe51d4a1c79d69472fbd4"}, + {file = "rpds_py-0.17.1-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:9051e3d2af8f55b42061603e29e744724cb5f65b128a491446cc029b3e2ea896"}, + {file = "rpds_py-0.17.1-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:7450dbd659fed6dd41d1a7d47ed767e893ba402af8ae664c157c255ec6067fde"}, + {file = "rpds_py-0.17.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:5a024fa96d541fd7edaa0e9d904601c6445e95a729a2900c5aec6555fe921ed6"}, + {file = "rpds_py-0.17.1-cp38-none-win32.whl", hash = "sha256:da1ead63368c04a9bded7904757dfcae01eba0e0f9bc41d3d7f57ebf1c04015a"}, + {file = "rpds_py-0.17.1-cp38-none-win_amd64.whl", hash = "sha256:841320e1841bb53fada91c9725e766bb25009cfd4144e92298db296fb6c894fb"}, + {file = "rpds_py-0.17.1-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:f6c43b6f97209e370124baf2bf40bb1e8edc25311a158867eb1c3a5d449ebc7a"}, + {file = "rpds_py-0.17.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:5e7d63ec01fe7c76c2dbb7e972fece45acbb8836e72682bde138e7e039906e2c"}, + {file = "rpds_py-0.17.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:81038ff87a4e04c22e1d81f947c6ac46f122e0c80460b9006e6517c4d842a6ec"}, + {file = "rpds_py-0.17.1-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:810685321f4a304b2b55577c915bece4c4a06dfe38f6e62d9cc1d6ca8ee86b99"}, + {file = "rpds_py-0.17.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:25f071737dae674ca8937a73d0f43f5a52e92c2d178330b4c0bb6ab05586ffa6"}, + {file = "rpds_py-0.17.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:aa5bfb13f1e89151ade0eb812f7b0d7a4d643406caaad65ce1cbabe0a66d695f"}, + {file = "rpds_py-0.17.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dfe07308b311a8293a0d5ef4e61411c5c20f682db6b5e73de6c7c8824272c256"}, + {file = "rpds_py-0.17.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a000133a90eea274a6f28adc3084643263b1e7c1a5a66eb0a0a7a36aa757ed74"}, + {file = "rpds_py-0.17.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:5d0e8a6434a3fbf77d11448c9c25b2f25244226cfbec1a5159947cac5b8c5fa4"}, + {file = "rpds_py-0.17.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:efa767c220d94aa4ac3a6dd3aeb986e9f229eaf5bce92d8b1b3018d06bed3772"}, + {file = "rpds_py-0.17.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:dbc56680ecf585a384fbd93cd42bc82668b77cb525343170a2d86dafaed2a84b"}, + {file = "rpds_py-0.17.1-cp39-none-win32.whl", hash = "sha256:270987bc22e7e5a962b1094953ae901395e8c1e1e83ad016c5cfcfff75a15a3f"}, + {file = "rpds_py-0.17.1-cp39-none-win_amd64.whl", hash = "sha256:2a7b2f2f56a16a6d62e55354dd329d929560442bd92e87397b7a9586a32e3e76"}, + {file = "rpds_py-0.17.1-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:a3264e3e858de4fc601741498215835ff324ff2482fd4e4af61b46512dd7fc83"}, + {file = "rpds_py-0.17.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:f2f3b28b40fddcb6c1f1f6c88c6f3769cd933fa493ceb79da45968a21dccc920"}, + {file = "rpds_py-0.17.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9584f8f52010295a4a417221861df9bea4c72d9632562b6e59b3c7b87a1522b7"}, + {file = "rpds_py-0.17.1-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c64602e8be701c6cfe42064b71c84ce62ce66ddc6422c15463fd8127db3d8066"}, + {file = "rpds_py-0.17.1-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:060f412230d5f19fc8c8b75f315931b408d8ebf56aec33ef4168d1b9e54200b1"}, + {file = "rpds_py-0.17.1-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b9412abdf0ba70faa6e2ee6c0cc62a8defb772e78860cef419865917d86c7342"}, + {file = "rpds_py-0.17.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9737bdaa0ad33d34c0efc718741abaafce62fadae72c8b251df9b0c823c63b22"}, + {file = "rpds_py-0.17.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9f0e4dc0f17dcea4ab9d13ac5c666b6b5337042b4d8f27e01b70fae41dd65c57"}, + {file = "rpds_py-0.17.1-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:1db228102ab9d1ff4c64148c96320d0be7044fa28bd865a9ce628ce98da5973d"}, + {file = "rpds_py-0.17.1-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:d8bbd8e56f3ba25a7d0cf980fc42b34028848a53a0e36c9918550e0280b9d0b6"}, + {file = "rpds_py-0.17.1-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:be22ae34d68544df293152b7e50895ba70d2a833ad9566932d750d3625918b82"}, + {file = "rpds_py-0.17.1-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:bf046179d011e6114daf12a534d874958b039342b347348a78b7cdf0dd9d6041"}, + {file = "rpds_py-0.17.1-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:1a746a6d49665058a5896000e8d9d2f1a6acba8a03b389c1e4c06e11e0b7f40d"}, + {file = "rpds_py-0.17.1-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f0b8bf5b8db49d8fd40f54772a1dcf262e8be0ad2ab0206b5a2ec109c176c0a4"}, + {file = "rpds_py-0.17.1-pp38-pypy38_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f7f4cb1f173385e8a39c29510dd11a78bf44e360fb75610594973f5ea141028b"}, + {file = "rpds_py-0.17.1-pp38-pypy38_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7fbd70cb8b54fe745301921b0816c08b6d917593429dfc437fd024b5ba713c58"}, + {file = "rpds_py-0.17.1-pp38-pypy38_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9bdf1303df671179eaf2cb41e8515a07fc78d9d00f111eadbe3e14262f59c3d0"}, + {file = "rpds_py-0.17.1-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fad059a4bd14c45776600d223ec194e77db6c20255578bb5bcdd7c18fd169361"}, + {file = "rpds_py-0.17.1-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:3664d126d3388a887db44c2e293f87d500c4184ec43d5d14d2d2babdb4c64cad"}, + {file = "rpds_py-0.17.1-pp38-pypy38_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:698ea95a60c8b16b58be9d854c9f993c639f5c214cf9ba782eca53a8789d6b19"}, + {file = "rpds_py-0.17.1-pp38-pypy38_pp73-musllinux_1_2_i686.whl", hash = "sha256:c3d2010656999b63e628a3c694f23020322b4178c450dc478558a2b6ef3cb9bb"}, + {file = "rpds_py-0.17.1-pp38-pypy38_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:938eab7323a736533f015e6069a7d53ef2dcc841e4e533b782c2bfb9fb12d84b"}, + {file = "rpds_py-0.17.1-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:1e626b365293a2142a62b9a614e1f8e331b28f3ca57b9f05ebbf4cf2a0f0bdc5"}, + {file = "rpds_py-0.17.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:380e0df2e9d5d5d339803cfc6d183a5442ad7ab3c63c2a0982e8c824566c5ccc"}, + {file = "rpds_py-0.17.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b760a56e080a826c2e5af09002c1a037382ed21d03134eb6294812dda268c811"}, + {file = "rpds_py-0.17.1-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5576ee2f3a309d2bb403ec292d5958ce03953b0e57a11d224c1f134feaf8c40f"}, + {file = "rpds_py-0.17.1-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1f3c3461ebb4c4f1bbc70b15d20b565759f97a5aaf13af811fcefc892e9197ba"}, + {file = "rpds_py-0.17.1-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:637b802f3f069a64436d432117a7e58fab414b4e27a7e81049817ae94de45d8d"}, + {file = "rpds_py-0.17.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ffee088ea9b593cc6160518ba9bd319b5475e5f3e578e4552d63818773c6f56a"}, + {file = "rpds_py-0.17.1-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:3ac732390d529d8469b831949c78085b034bff67f584559340008d0f6041a049"}, + {file = "rpds_py-0.17.1-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:93432e747fb07fa567ad9cc7aaadd6e29710e515aabf939dfbed8046041346c6"}, + {file = "rpds_py-0.17.1-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:7b7d9ca34542099b4e185b3c2a2b2eda2e318a7dbde0b0d83357a6d4421b5296"}, + {file = "rpds_py-0.17.1-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:0387ce69ba06e43df54e43968090f3626e231e4bc9150e4c3246947567695f68"}, + {file = "rpds_py-0.17.1.tar.gz", hash = "sha256:0210b2668f24c078307260bf88bdac9d6f1093635df5123789bfee4d8d7fc8e7"}, ] [[package]] @@ -2938,20 +2941,18 @@ test = ["pytest"] [[package]] name = "sphinxcontrib-applehelp" -version = "1.0.7" +version = "1.0.8" description = "sphinxcontrib-applehelp is a Sphinx extension which outputs Apple help books" optional = true python-versions = ">=3.9" files = [ - {file = "sphinxcontrib_applehelp-1.0.7-py3-none-any.whl", hash = "sha256:094c4d56209d1734e7d252f6e0b3ccc090bd52ee56807a5d9315b19c122ab15d"}, - {file = "sphinxcontrib_applehelp-1.0.7.tar.gz", hash = "sha256:39fdc8d762d33b01a7d8f026a3b7d71563ea3b72787d5f00ad8465bd9d6dfbfa"}, + {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.dependencies] -Sphinx = ">=5" - [package.extras] lint = ["docutils-stubs", "flake8", "mypy"] +standalone = ["Sphinx (>=5)"] test = ["pytest"] [[package]] @@ -2971,20 +2972,18 @@ test = ["pytest"] [[package]] name = "sphinxcontrib-devhelp" -version = "1.0.5" +version = "1.0.6" description = "sphinxcontrib-devhelp is a sphinx extension which outputs Devhelp documents" optional = true python-versions = ">=3.9" files = [ - {file = "sphinxcontrib_devhelp-1.0.5-py3-none-any.whl", hash = "sha256:fe8009aed765188f08fcaadbb3ea0d90ce8ae2d76710b7e29ea7d047177dae2f"}, - {file = "sphinxcontrib_devhelp-1.0.5.tar.gz", hash = "sha256:63b41e0d38207ca40ebbeabcf4d8e51f76c03e78cd61abe118cf4435c73d4212"}, + {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.dependencies] -Sphinx = ">=5" - [package.extras] lint = ["docutils-stubs", "flake8", "mypy"] +standalone = ["Sphinx (>=5)"] test = ["pytest"] [[package]] @@ -3004,20 +3003,18 @@ test = ["html5lib", "pytest"] [[package]] name = "sphinxcontrib-htmlhelp" -version = "2.0.4" +version = "2.0.5" description = "sphinxcontrib-htmlhelp is a sphinx extension which renders HTML help files" optional = true python-versions = ">=3.9" files = [ - {file = "sphinxcontrib_htmlhelp-2.0.4-py3-none-any.whl", hash = "sha256:8001661c077a73c29beaf4a79968d0726103c5605e27db92b9ebed8bab1359e9"}, - {file = "sphinxcontrib_htmlhelp-2.0.4.tar.gz", hash = "sha256:6c26a118a05b76000738429b724a0568dbde5b72391a688577da08f11891092a"}, + {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.dependencies] -Sphinx = ">=5" - [package.extras] lint = ["docutils-stubs", "flake8", "mypy"] +standalone = ["Sphinx (>=5)"] test = ["html5lib", "pytest"] [[package]] @@ -3051,20 +3048,18 @@ test = ["pytest"] [[package]] name = "sphinxcontrib-qthelp" -version = "1.0.6" +version = "1.0.7" description = "sphinxcontrib-qthelp is a sphinx extension which outputs QtHelp documents" optional = true python-versions = ">=3.9" files = [ - {file = "sphinxcontrib_qthelp-1.0.6-py3-none-any.whl", hash = "sha256:bf76886ee7470b934e363da7a954ea2825650013d367728588732c7350f49ea4"}, - {file = "sphinxcontrib_qthelp-1.0.6.tar.gz", hash = "sha256:62b9d1a186ab7f5ee3356d906f648cacb7a6bdb94d201ee7adf26db55092982d"}, + {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.dependencies] -Sphinx = ">=5" - [package.extras] lint = ["docutils-stubs", "flake8", "mypy"] +standalone = ["Sphinx (>=5)"] test = ["pytest"] [[package]] @@ -3084,20 +3079,18 @@ test = ["pytest"] [[package]] name = "sphinxcontrib-serializinghtml" -version = "1.1.9" +version = "1.1.10" description = "sphinxcontrib-serializinghtml is a sphinx extension which outputs \"serialized\" HTML files (json and pickle)" optional = true python-versions = ">=3.9" files = [ - {file = "sphinxcontrib_serializinghtml-1.1.9-py3-none-any.whl", hash = "sha256:9b36e503703ff04f20e9675771df105e58aa029cfcbc23b8ed716019b7416ae1"}, - {file = "sphinxcontrib_serializinghtml-1.1.9.tar.gz", hash = "sha256:0c64ff898339e1fac29abd2bf5f11078f3ec413cfe9c046d3120d7ca65530b54"}, + {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.dependencies] -Sphinx = ">=5" - [package.extras] lint = ["docutils-stubs", "flake8", "mypy"] +standalone = ["Sphinx (>=5)"] test = ["pytest"] [[package]] @@ -3587,4 +3580,4 @@ virustotal = ["validators"] [metadata] lock-version = "2.0" python-versions = "^3.8" -content-hash = "096b132456e7298b277cc4a78773b394516e649d44aa12eb86d8a2ba7704429b" +content-hash = "fcf4e884ba74ca8562dc557ddc5270888f57f1e34dd773de9825c0f3e6e5f4c8" diff --git a/pyproject.toml b/pyproject.toml index d64a99c..f42ac2d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -50,7 +50,7 @@ oletools = {version = "^0.60.1", optional = true} python-magic = {version = "^0.4.27", optional = true} pydeep2 = {version = "^0.5.1", optional = true} lief = {version = "^0.13.2", optional = true} -beautifulsoup4 = {version = "^4.12.2", optional = true} +beautifulsoup4 = {version = "^4.12.3", optional = true} validators = {version = "^0.22.0", optional = true} sphinx-autodoc-typehints = {version = "^1.25.2", optional = true} recommonmark = {version = "^0.7.1", optional = true} From dbe29f87f34c4391e92a5cc9380a834d223491fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Vinot?= Date: Mon, 22 Jan 2024 10:34:14 +0100 Subject: [PATCH 44/80] new: Enable support for python 3.12. --- .github/workflows/pytest.yml | 2 +- poetry.lock | 237 ++++++++++++++++++----------------- pyproject.toml | 5 +- 3 files changed, 126 insertions(+), 118 deletions(-) diff --git a/.github/workflows/pytest.yml b/.github/workflows/pytest.yml index febc048..f61ef93 100644 --- a/.github/workflows/pytest.yml +++ b/.github/workflows/pytest.yml @@ -13,7 +13,7 @@ jobs: strategy: fail-fast: false matrix: - python-version: [3.8, 3.9, '3.10', '3.11'] + python-version: [3.8, 3.9, '3.10', '3.11', '3.12'] steps: diff --git a/poetry.lock b/poetry.lock index 1bc7019..2703083 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1238,13 +1238,13 @@ files = [ [[package]] name = "jsonschema" -version = "4.21.0" +version = "4.21.1" description = "An implementation of JSON Schema validation for Python" optional = false python-versions = ">=3.8" files = [ - {file = "jsonschema-4.21.0-py3-none-any.whl", hash = "sha256:70a09719d375c0a2874571b363c8a24be7df8071b80c9aa76bc4551e7297c63c"}, - {file = "jsonschema-4.21.0.tar.gz", hash = "sha256:3ba18e27f7491ea4a1b22edce00fb820eec968d397feb3f9cb61d5894bb38167"}, + {file = "jsonschema-4.21.1-py3-none-any.whl", hash = "sha256:7996507afae316306f9e2290407761157c6f78002dcf7419acb99822143d1c6f"}, + {file = "jsonschema-4.21.1.tar.gz", hash = "sha256:85727c00279f5fa6bedbe6238d2aa6403bedd8b4864ab11207d07df3cc1b2ee5"}, ] [package.dependencies] @@ -1422,13 +1422,13 @@ test = ["jupyter-server (>=2.0.0)", "pytest (>=7.0)", "pytest-jupyter[server] (> [[package]] name = "jupyterlab" -version = "4.0.10" +version = "4.0.11" description = "JupyterLab computational environment" optional = false python-versions = ">=3.8" files = [ - {file = "jupyterlab-4.0.10-py3-none-any.whl", hash = "sha256:fe010ad9e37017488b468632ef2ead255fc7c671c5b64d9ca13e1f7b7e665c37"}, - {file = "jupyterlab-4.0.10.tar.gz", hash = "sha256:46177eb8ede70dc73be922ac99f8ef943bdc2dfbc6a31b353c4bde848a35dee1"}, + {file = "jupyterlab-4.0.11-py3-none-any.whl", hash = "sha256:536bf0e78723153a5016ca7efb88ed0ecd7070d3f1555d5b0e2770658f900a3c"}, + {file = "jupyterlab-4.0.11.tar.gz", hash = "sha256:d1aec24712566bc25a36229788242778e498ca4088028e2f9aa156b8b7fdc8fc"}, ] [package.dependencies] @@ -1509,103 +1509,110 @@ regex = ["regex"] [[package]] name = "lief" -version = "0.13.2" +version = "0.14.0" description = "Library to instrument executable formats" optional = true python-versions = ">=3.8" files = [ - {file = "lief-0.13.2-cp310-cp310-macosx_10_14_x86_64.whl", hash = "sha256:0390cfaaf0e9aed46bebf26f00f34852768f76bc7f90abf7ceb384566200e5f5"}, - {file = "lief-0.13.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:5581bf0072c1e7a9ea2fb2e2252b8582016e8b298804b5461e552b402c9cd4e9"}, - {file = "lief-0.13.2-cp310-cp310-manylinux2014_aarch64.whl", hash = "sha256:dbbf2fb3d7807e815f345c77e287da162e081100f059ec03005995befc295d7f"}, - {file = "lief-0.13.2-cp310-cp310-manylinux_2_24_x86_64.whl", hash = "sha256:d344d37334c2b488dc02f04cb13c22cd61aa065eeb9bca7424588e0c8c23bdfb"}, - {file = "lief-0.13.2-cp310-cp310-win32.whl", hash = "sha256:bc041b28b94139843a33c014e355822a9276b35f3c5ae10d82da56bf572f8222"}, - {file = "lief-0.13.2-cp310-cp310-win_amd64.whl", hash = "sha256:01d4075bbc3541e9dd3ef008045fa1eb128294a0c5b0c1f69ce60d8948d248c7"}, - {file = "lief-0.13.2-cp311-cp311-macosx_10_14_x86_64.whl", hash = "sha256:6570dacebe107ad60c2ba0968d1a865d316009d43cc85af3719d3eeb0911abf3"}, - {file = "lief-0.13.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7ce2e3f7c791efba327c2bb3499dbef81e682027109045a9bae696c62e2aeeb0"}, - {file = "lief-0.13.2-cp311-cp311-manylinux2014_aarch64.whl", hash = "sha256:11ab900e0644b6735ecdef2bbd04439b4866a527650fc054470c195d6cfe2917"}, - {file = "lief-0.13.2-cp311-cp311-manylinux_2_24_x86_64.whl", hash = "sha256:042ad2105a136b11a7494b9af8178468e8cb32b8fa2a0a55cb659a5605aeb069"}, - {file = "lief-0.13.2-cp311-cp311-win32.whl", hash = "sha256:1ce289b6ab3cf4be654270007e8a2c0d2e42116180418c29d3ce83762955de63"}, - {file = "lief-0.13.2-cp311-cp311-win_amd64.whl", hash = "sha256:eccb248ffb598e410fd2ef7c1f171a3cde57a40c9bb8c4fa15d8e7b90eb4eb2d"}, - {file = "lief-0.13.2-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:95731cadedd6ffc5fb48c147fcefe004624e436b75e8ee9fb2dbf2ae5f084342"}, - {file = "lief-0.13.2-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:8da75df0ea472557fcc37a27ba583bad5a8f3a256c186600d00a6dd0a57f718a"}, - {file = "lief-0.13.2-cp38-cp38-manylinux_2_24_x86_64.whl", hash = "sha256:b99092f02c13f580c2d00b504af224b7e60e7c98a791e72ae8519f530b7687bb"}, - {file = "lief-0.13.2-cp38-cp38-win32.whl", hash = "sha256:03db0138e4dbbdfa8bba74de312b0cebb30f504e44f38a9c8918b84022da340b"}, - {file = "lief-0.13.2-cp38-cp38-win_amd64.whl", hash = "sha256:36c5bea3f8460dee3ebb75d35949f445638ec85d2871f31e293c47fb4a0a5af7"}, - {file = "lief-0.13.2-cp39-cp39-macosx_10_14_x86_64.whl", hash = "sha256:eca8ecbcae1ad851ed7cf1e22ec8accd74f2267fa7375194559fb917523d8a92"}, - {file = "lief-0.13.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a8703cb5308b4828563badc6885ff07a3926ec3403d1caa3aa75f24fe9cbcf84"}, - {file = "lief-0.13.2-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:c60f2f79e7d0d1f18dec7dcdb4d4f35e6b126ac29e2f2f056d28ec50599d868a"}, - {file = "lief-0.13.2-cp39-cp39-manylinux_2_24_x86_64.whl", hash = "sha256:e0f84a7443b7f1b02666fd16a9aa57f5d9027e60ba2885e0d76db8426d689707"}, - {file = "lief-0.13.2-cp39-cp39-win32.whl", hash = "sha256:3f8f251de874929d9c9e94a35891621ab8c059149f8a1c24e543fd9cf0c2a31c"}, - {file = "lief-0.13.2-cp39-cp39-win_amd64.whl", hash = "sha256:2bbe294385e629aa7206b2f39f0ca34e3948605a8db50b22091603053889a759"}, + {file = "lief-0.14.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:b1e9af189e0dcbd6ce9ce67266135ef288c9b8f9a5efe2a47d0d0266288713cf"}, + {file = "lief-0.14.0-cp310-cp310-macosx_11_0_x86_64.whl", hash = "sha256:60be24af0b913a79922a9730302df5f380954a1d7b1c0c7de91b8918e36f0756"}, + {file = "lief-0.14.0-cp310-cp310-manylinux2014_aarch64.whl", hash = "sha256:1d949c53f95132ef0d218e88c3c982610c54426249c95f99b736e5c15bb1b75b"}, + {file = "lief-0.14.0-cp310-cp310-manylinux_2_28_x86_64.manylinux_2_27_x86_64.whl", hash = "sha256:51e7adfe1cc574a035b47a280cb5902cec6deb2d78ef0b47c536bdd75dfa6956"}, + {file = "lief-0.14.0-cp310-cp310-win32.whl", hash = "sha256:b34708c002c119f43998af3c4f219d06de6b66a34aceb298fd8bba8247e57572"}, + {file = "lief-0.14.0-cp310-cp310-win_amd64.whl", hash = "sha256:684c1500fddab8aaf5a4f74cd092ea190c4c837d31c5d087c68a9f175775c2db"}, + {file = "lief-0.14.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:737bd6fab74e222968936794e09b2bf399417c38a3bc13d6ad70836793e78586"}, + {file = "lief-0.14.0-cp311-cp311-macosx_11_0_x86_64.whl", hash = "sha256:ff42aa1f12d3dc8bc5641eb1991269fb92e43bae386559ad576c97ffa09639f2"}, + {file = "lief-0.14.0-cp311-cp311-manylinux2014_aarch64.whl", hash = "sha256:69df631cd0573388fa6891277d006f8da2fa42a5bbe3acc440b66a7352f6bef3"}, + {file = "lief-0.14.0-cp311-cp311-manylinux_2_28_x86_64.manylinux_2_27_x86_64.whl", hash = "sha256:b850f38b62ca8a92c7f9803ceac0e79369b732a75e627cba3c2b8f1fa729f643"}, + {file = "lief-0.14.0-cp311-cp311-win32.whl", hash = "sha256:ba29aabd72e92334d54883d58b108f80465973edaec3e27cb422abbc657bfe17"}, + {file = "lief-0.14.0-cp311-cp311-win_amd64.whl", hash = "sha256:33f2afdf9f00a8a208d5f32135834fc5f02bd12e8b14f0857cf14d4475ad03bb"}, + {file = "lief-0.14.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:70b53498390e8b95d878598c95bd068f5c86cab415c3869538fbce4cee36a9cc"}, + {file = "lief-0.14.0-cp312-cp312-macosx_11_0_x86_64.whl", hash = "sha256:c49d34c9140a4b77046137ceeeb872f26262447f514ccbf0cc985a91e59e7f69"}, + {file = "lief-0.14.0-cp312-cp312-manylinux2014_aarch64.whl", hash = "sha256:46808f2ec6903d8a4a4a4975d664e70c64ca11691bacb391a51029a8cb941e92"}, + {file = "lief-0.14.0-cp312-cp312-manylinux_2_28_x86_64.manylinux_2_27_x86_64.whl", hash = "sha256:4e6ca44bc9d0d314ac73148c64e4f9182c950a2f2024ab9d3d7100635d46261a"}, + {file = "lief-0.14.0-cp312-cp312-win32.whl", hash = "sha256:17e2809fa52e377d1a5045dbbbdea8bebbaad7f672d6c133287388e7e9942b64"}, + {file = "lief-0.14.0-cp312-cp312-win_amd64.whl", hash = "sha256:5713e27ba7bbe7c8c503354f3555a33e69d5236a02dd34d162156cc85a9b88b5"}, + {file = "lief-0.14.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:9998bd60d332b50f72fb71d22316b227f9fdbb301c953e8aa003822a80a6ed0a"}, + {file = "lief-0.14.0-cp38-cp38-macosx_11_0_x86_64.whl", hash = "sha256:fe783a180d63aa3ae19c5f58dc76afc179f40249c4c77d9f70bc557255b4051b"}, + {file = "lief-0.14.0-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:28e847e8410b9101f49af0ae9d06e7cb2d0db64c47442ac4c79abf1b15b2c108"}, + {file = "lief-0.14.0-cp38-cp38-manylinux_2_28_x86_64.manylinux_2_27_x86_64.whl", hash = "sha256:4a44d5bd2462c9db68227ed9193243c412ce6153fe6a8e53782ff4210e4606ab"}, + {file = "lief-0.14.0-cp38-cp38-win32.whl", hash = "sha256:0a0754079d595c9e3ceffed9e32d309ed139b1433fad9ad37aaa35e6a8e67d70"}, + {file = "lief-0.14.0-cp38-cp38-win_amd64.whl", hash = "sha256:bc8647f050728c09645666765de6dcbc681df7b0b6bdcfb4cdbbb96a523d2eaa"}, + {file = "lief-0.14.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:7f89b8e3cc6aa01f50a8ed58d5aea89f6d767df7951fd050659e9617c1b4eb45"}, + {file = "lief-0.14.0-cp39-cp39-macosx_11_0_x86_64.whl", hash = "sha256:110705c186f2ddc13fc2fad0dc9d501742d785b934103fdf56e86a86bcbcac1d"}, + {file = "lief-0.14.0-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:0ba07f12c00950554d29495c3aef3740c44243d1c0d80a3f8dadf64c456a32e7"}, + {file = "lief-0.14.0-cp39-cp39-manylinux_2_28_x86_64.manylinux_2_27_x86_64.whl", hash = "sha256:f237042467f41bf0e64b051e780865f9aef958ddec1a358317cc259da2ec2a16"}, + {file = "lief-0.14.0-cp39-cp39-win32.whl", hash = "sha256:75c7daefe56ba91ad4fc0a5e6573ca3c79dea2e938787b285b31ac0c25c5e5c3"}, + {file = "lief-0.14.0-cp39-cp39-win_amd64.whl", hash = "sha256:583d37400c85dc80299db873d380c0901995ae03606f7de50fd3d0538e7a7860"}, ] [[package]] name = "markupsafe" -version = "2.1.3" +version = "2.1.4" description = "Safely add untrusted strings to HTML/XML markup." optional = false python-versions = ">=3.7" files = [ - {file = "MarkupSafe-2.1.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:cd0f502fe016460680cd20aaa5a76d241d6f35a1c3350c474bac1273803893fa"}, - {file = "MarkupSafe-2.1.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e09031c87a1e51556fdcb46e5bd4f59dfb743061cf93c4d6831bf894f125eb57"}, - {file = "MarkupSafe-2.1.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:68e78619a61ecf91e76aa3e6e8e33fc4894a2bebe93410754bd28fce0a8a4f9f"}, - {file = "MarkupSafe-2.1.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:65c1a9bcdadc6c28eecee2c119465aebff8f7a584dd719facdd9e825ec61ab52"}, - {file = "MarkupSafe-2.1.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:525808b8019e36eb524b8c68acdd63a37e75714eac50e988180b169d64480a00"}, - {file = "MarkupSafe-2.1.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:962f82a3086483f5e5f64dbad880d31038b698494799b097bc59c2edf392fce6"}, - {file = "MarkupSafe-2.1.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:aa7bd130efab1c280bed0f45501b7c8795f9fdbeb02e965371bbef3523627779"}, - {file = "MarkupSafe-2.1.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c9c804664ebe8f83a211cace637506669e7890fec1b4195b505c214e50dd4eb7"}, - {file = "MarkupSafe-2.1.3-cp310-cp310-win32.whl", hash = "sha256:10bbfe99883db80bdbaff2dcf681dfc6533a614f700da1287707e8a5d78a8431"}, - {file = "MarkupSafe-2.1.3-cp310-cp310-win_amd64.whl", hash = "sha256:1577735524cdad32f9f694208aa75e422adba74f1baee7551620e43a3141f559"}, - {file = "MarkupSafe-2.1.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ad9e82fb8f09ade1c3e1b996a6337afac2b8b9e365f926f5a61aacc71adc5b3c"}, - {file = "MarkupSafe-2.1.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3c0fae6c3be832a0a0473ac912810b2877c8cb9d76ca48de1ed31e1c68386575"}, - {file = "MarkupSafe-2.1.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b076b6226fb84157e3f7c971a47ff3a679d837cf338547532ab866c57930dbee"}, - {file = "MarkupSafe-2.1.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bfce63a9e7834b12b87c64d6b155fdd9b3b96191b6bd334bf37db7ff1fe457f2"}, - {file = "MarkupSafe-2.1.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:338ae27d6b8745585f87218a3f23f1512dbf52c26c28e322dbe54bcede54ccb9"}, - {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e4dd52d80b8c83fdce44e12478ad2e85c64ea965e75d66dbeafb0a3e77308fcc"}, - {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:df0be2b576a7abbf737b1575f048c23fb1d769f267ec4358296f31c2479db8f9"}, - {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:5bbe06f8eeafd38e5d0a4894ffec89378b6c6a625ff57e3028921f8ff59318ac"}, - {file = "MarkupSafe-2.1.3-cp311-cp311-win32.whl", hash = "sha256:dd15ff04ffd7e05ffcb7fe79f1b98041b8ea30ae9234aed2a9168b5797c3effb"}, - {file = "MarkupSafe-2.1.3-cp311-cp311-win_amd64.whl", hash = "sha256:134da1eca9ec0ae528110ccc9e48041e0828d79f24121a1a146161103c76e686"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:f698de3fd0c4e6972b92290a45bd9b1536bffe8c6759c62471efaa8acb4c37bc"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:aa57bd9cf8ae831a362185ee444e15a93ecb2e344c8e52e4d721ea3ab6ef1823"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ffcc3f7c66b5f5b7931a5aa68fc9cecc51e685ef90282f4a82f0f5e9b704ad11"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47d4f1c5f80fc62fdd7777d0d40a2e9dda0a05883ab11374334f6c4de38adffd"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1f67c7038d560d92149c060157d623c542173016c4babc0c1913cca0564b9939"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:9aad3c1755095ce347e26488214ef77e0485a3c34a50c5a5e2471dff60b9dd9c"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:14ff806850827afd6b07a5f32bd917fb7f45b046ba40c57abdb636674a8b559c"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8f9293864fe09b8149f0cc42ce56e3f0e54de883a9de90cd427f191c346eb2e1"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-win32.whl", hash = "sha256:715d3562f79d540f251b99ebd6d8baa547118974341db04f5ad06d5ea3eb8007"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-win_amd64.whl", hash = "sha256:1b8dd8c3fd14349433c79fa8abeb573a55fc0fdd769133baac1f5e07abf54aeb"}, - {file = "MarkupSafe-2.1.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:8e254ae696c88d98da6555f5ace2279cf7cd5b3f52be2b5cf97feafe883b58d2"}, - {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb0932dc158471523c9637e807d9bfb93e06a95cbf010f1a38b98623b929ef2b"}, - {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9402b03f1a1b4dc4c19845e5c749e3ab82d5078d16a2a4c2cd2df62d57bb0707"}, - {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ca379055a47383d02a5400cb0d110cef0a776fc644cda797db0c5696cfd7e18e"}, - {file = "MarkupSafe-2.1.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:b7ff0f54cb4ff66dd38bebd335a38e2c22c41a8ee45aa608efc890ac3e3931bc"}, - {file = "MarkupSafe-2.1.3-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:c011a4149cfbcf9f03994ec2edffcb8b1dc2d2aede7ca243746df97a5d41ce48"}, - {file = "MarkupSafe-2.1.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:56d9f2ecac662ca1611d183feb03a3fa4406469dafe241673d521dd5ae92a155"}, - {file = "MarkupSafe-2.1.3-cp37-cp37m-win32.whl", hash = "sha256:8758846a7e80910096950b67071243da3e5a20ed2546e6392603c096778d48e0"}, - {file = "MarkupSafe-2.1.3-cp37-cp37m-win_amd64.whl", hash = "sha256:787003c0ddb00500e49a10f2844fac87aa6ce977b90b0feaaf9de23c22508b24"}, - {file = "MarkupSafe-2.1.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:2ef12179d3a291be237280175b542c07a36e7f60718296278d8593d21ca937d4"}, - {file = "MarkupSafe-2.1.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2c1b19b3aaacc6e57b7e25710ff571c24d6c3613a45e905b1fde04d691b98ee0"}, - {file = "MarkupSafe-2.1.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8afafd99945ead6e075b973fefa56379c5b5c53fd8937dad92c662da5d8fd5ee"}, - {file = "MarkupSafe-2.1.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8c41976a29d078bb235fea9b2ecd3da465df42a562910f9022f1a03107bd02be"}, - {file = "MarkupSafe-2.1.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d080e0a5eb2529460b30190fcfcc4199bd7f827663f858a226a81bc27beaa97e"}, - {file = "MarkupSafe-2.1.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:69c0f17e9f5a7afdf2cc9fb2d1ce6aabdb3bafb7f38017c0b77862bcec2bbad8"}, - {file = "MarkupSafe-2.1.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:504b320cd4b7eff6f968eddf81127112db685e81f7e36e75f9f84f0df46041c3"}, - {file = "MarkupSafe-2.1.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:42de32b22b6b804f42c5d98be4f7e5e977ecdd9ee9b660fda1a3edf03b11792d"}, - {file = "MarkupSafe-2.1.3-cp38-cp38-win32.whl", hash = "sha256:ceb01949af7121f9fc39f7d27f91be8546f3fb112c608bc4029aef0bab86a2a5"}, - {file = "MarkupSafe-2.1.3-cp38-cp38-win_amd64.whl", hash = "sha256:1b40069d487e7edb2676d3fbdb2b0829ffa2cd63a2ec26c4938b2d34391b4ecc"}, - {file = "MarkupSafe-2.1.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:8023faf4e01efadfa183e863fefde0046de576c6f14659e8782065bcece22198"}, - {file = "MarkupSafe-2.1.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6b2b56950d93e41f33b4223ead100ea0fe11f8e6ee5f641eb753ce4b77a7042b"}, - {file = "MarkupSafe-2.1.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9dcdfd0eaf283af041973bff14a2e143b8bd64e069f4c383416ecd79a81aab58"}, - {file = "MarkupSafe-2.1.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:05fb21170423db021895e1ea1e1f3ab3adb85d1c2333cbc2310f2a26bc77272e"}, - {file = "MarkupSafe-2.1.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:282c2cb35b5b673bbcadb33a585408104df04f14b2d9b01d4c345a3b92861c2c"}, - {file = "MarkupSafe-2.1.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ab4a0df41e7c16a1392727727e7998a467472d0ad65f3ad5e6e765015df08636"}, - {file = "MarkupSafe-2.1.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:7ef3cb2ebbf91e330e3bb937efada0edd9003683db6b57bb108c4001f37a02ea"}, - {file = "MarkupSafe-2.1.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:0a4e4a1aff6c7ac4cd55792abf96c915634c2b97e3cc1c7129578aa68ebd754e"}, - {file = "MarkupSafe-2.1.3-cp39-cp39-win32.whl", hash = "sha256:fec21693218efe39aa7f8599346e90c705afa52c5b31ae019b2e57e8f6542bb2"}, - {file = "MarkupSafe-2.1.3-cp39-cp39-win_amd64.whl", hash = "sha256:3fd4abcb888d15a94f32b75d8fd18ee162ca0c064f35b11134be77050296d6ba"}, - {file = "MarkupSafe-2.1.3.tar.gz", hash = "sha256:af598ed32d6ae86f1b747b82783958b1a4ab8f617b06fe68795c7f026abbdcad"}, + {file = "MarkupSafe-2.1.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:de8153a7aae3835484ac168a9a9bdaa0c5eee4e0bc595503c95d53b942879c84"}, + {file = "MarkupSafe-2.1.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e888ff76ceb39601c59e219f281466c6d7e66bd375b4ec1ce83bcdc68306796b"}, + {file = "MarkupSafe-2.1.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0b838c37ba596fcbfca71651a104a611543077156cb0a26fe0c475e1f152ee8"}, + {file = "MarkupSafe-2.1.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dac1ebf6983148b45b5fa48593950f90ed6d1d26300604f321c74a9ca1609f8e"}, + {file = "MarkupSafe-2.1.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0fbad3d346df8f9d72622ac71b69565e621ada2ce6572f37c2eae8dacd60385d"}, + {file = "MarkupSafe-2.1.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:d5291d98cd3ad9a562883468c690a2a238c4a6388ab3bd155b0c75dd55ece858"}, + {file = "MarkupSafe-2.1.4-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:a7cc49ef48a3c7a0005a949f3c04f8baa5409d3f663a1b36f0eba9bfe2a0396e"}, + {file = "MarkupSafe-2.1.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:b83041cda633871572f0d3c41dddd5582ad7d22f65a72eacd8d3d6d00291df26"}, + {file = "MarkupSafe-2.1.4-cp310-cp310-win32.whl", hash = "sha256:0c26f67b3fe27302d3a412b85ef696792c4a2386293c53ba683a89562f9399b0"}, + {file = "MarkupSafe-2.1.4-cp310-cp310-win_amd64.whl", hash = "sha256:a76055d5cb1c23485d7ddae533229039b850db711c554a12ea64a0fd8a0129e2"}, + {file = "MarkupSafe-2.1.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9e9e3c4020aa2dc62d5dd6743a69e399ce3de58320522948af6140ac959ab863"}, + {file = "MarkupSafe-2.1.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:0042d6a9880b38e1dd9ff83146cc3c9c18a059b9360ceae207805567aacccc69"}, + {file = "MarkupSafe-2.1.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:55d03fea4c4e9fd0ad75dc2e7e2b6757b80c152c032ea1d1de487461d8140efc"}, + {file = "MarkupSafe-2.1.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ab3a886a237f6e9c9f4f7d272067e712cdb4efa774bef494dccad08f39d8ae6"}, + {file = "MarkupSafe-2.1.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:abf5ebbec056817057bfafc0445916bb688a255a5146f900445d081db08cbabb"}, + {file = "MarkupSafe-2.1.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e1a0d1924a5013d4f294087e00024ad25668234569289650929ab871231668e7"}, + {file = "MarkupSafe-2.1.4-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:e7902211afd0af05fbadcc9a312e4cf10f27b779cf1323e78d52377ae4b72bea"}, + {file = "MarkupSafe-2.1.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:c669391319973e49a7c6230c218a1e3044710bc1ce4c8e6eb71f7e6d43a2c131"}, + {file = "MarkupSafe-2.1.4-cp311-cp311-win32.whl", hash = "sha256:31f57d64c336b8ccb1966d156932f3daa4fee74176b0fdc48ef580be774aae74"}, + {file = "MarkupSafe-2.1.4-cp311-cp311-win_amd64.whl", hash = "sha256:54a7e1380dfece8847c71bf7e33da5d084e9b889c75eca19100ef98027bd9f56"}, + {file = "MarkupSafe-2.1.4-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:a76cd37d229fc385738bd1ce4cba2a121cf26b53864c1772694ad0ad348e509e"}, + {file = "MarkupSafe-2.1.4-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:987d13fe1d23e12a66ca2073b8d2e2a75cec2ecb8eab43ff5624ba0ad42764bc"}, + {file = "MarkupSafe-2.1.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5244324676254697fe5c181fc762284e2c5fceeb1c4e3e7f6aca2b6f107e60dc"}, + {file = "MarkupSafe-2.1.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:78bc995e004681246e85e28e068111a4c3f35f34e6c62da1471e844ee1446250"}, + {file = "MarkupSafe-2.1.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a4d176cfdfde84f732c4a53109b293d05883e952bbba68b857ae446fa3119b4f"}, + {file = "MarkupSafe-2.1.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:f9917691f410a2e0897d1ef99619fd3f7dd503647c8ff2475bf90c3cf222ad74"}, + {file = "MarkupSafe-2.1.4-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:f06e5a9e99b7df44640767842f414ed5d7bedaaa78cd817ce04bbd6fd86e2dd6"}, + {file = "MarkupSafe-2.1.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:396549cea79e8ca4ba65525470d534e8a41070e6b3500ce2414921099cb73e8d"}, + {file = "MarkupSafe-2.1.4-cp312-cp312-win32.whl", hash = "sha256:f6be2d708a9d0e9b0054856f07ac7070fbe1754be40ca8525d5adccdbda8f475"}, + {file = "MarkupSafe-2.1.4-cp312-cp312-win_amd64.whl", hash = "sha256:5045e892cfdaecc5b4c01822f353cf2c8feb88a6ec1c0adef2a2e705eef0f656"}, + {file = "MarkupSafe-2.1.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:7a07f40ef8f0fbc5ef1000d0c78771f4d5ca03b4953fc162749772916b298fc4"}, + {file = "MarkupSafe-2.1.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d18b66fe626ac412d96c2ab536306c736c66cf2a31c243a45025156cc190dc8a"}, + {file = "MarkupSafe-2.1.4-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:698e84142f3f884114ea8cf83e7a67ca8f4ace8454e78fe960646c6c91c63bfa"}, + {file = "MarkupSafe-2.1.4-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:49a3b78a5af63ec10d8604180380c13dcd870aba7928c1fe04e881d5c792dc4e"}, + {file = "MarkupSafe-2.1.4-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:15866d7f2dc60cfdde12ebb4e75e41be862348b4728300c36cdf405e258415ec"}, + {file = "MarkupSafe-2.1.4-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:6aa5e2e7fc9bc042ae82d8b79d795b9a62bd8f15ba1e7594e3db243f158b5565"}, + {file = "MarkupSafe-2.1.4-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:54635102ba3cf5da26eb6f96c4b8c53af8a9c0d97b64bdcb592596a6255d8518"}, + {file = "MarkupSafe-2.1.4-cp37-cp37m-win32.whl", hash = "sha256:3583a3a3ab7958e354dc1d25be74aee6228938312ee875a22330c4dc2e41beb0"}, + {file = "MarkupSafe-2.1.4-cp37-cp37m-win_amd64.whl", hash = "sha256:d6e427c7378c7f1b2bef6a344c925b8b63623d3321c09a237b7cc0e77dd98ceb"}, + {file = "MarkupSafe-2.1.4-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:bf1196dcc239e608605b716e7b166eb5faf4bc192f8a44b81e85251e62584bd2"}, + {file = "MarkupSafe-2.1.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:4df98d4a9cd6a88d6a585852f56f2155c9cdb6aec78361a19f938810aa020954"}, + {file = "MarkupSafe-2.1.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b835aba863195269ea358cecc21b400276747cc977492319fd7682b8cd2c253d"}, + {file = "MarkupSafe-2.1.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:23984d1bdae01bee794267424af55eef4dfc038dc5d1272860669b2aa025c9e3"}, + {file = "MarkupSafe-2.1.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1c98c33ffe20e9a489145d97070a435ea0679fddaabcafe19982fe9c971987d5"}, + {file = "MarkupSafe-2.1.4-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:9896fca4a8eb246defc8b2a7ac77ef7553b638e04fbf170bff78a40fa8a91474"}, + {file = "MarkupSafe-2.1.4-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:b0fe73bac2fed83839dbdbe6da84ae2a31c11cfc1c777a40dbd8ac8a6ed1560f"}, + {file = "MarkupSafe-2.1.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:c7556bafeaa0a50e2fe7dc86e0382dea349ebcad8f010d5a7dc6ba568eaaa789"}, + {file = "MarkupSafe-2.1.4-cp38-cp38-win32.whl", hash = "sha256:fc1a75aa8f11b87910ffd98de62b29d6520b6d6e8a3de69a70ca34dea85d2a8a"}, + {file = "MarkupSafe-2.1.4-cp38-cp38-win_amd64.whl", hash = "sha256:3a66c36a3864df95e4f62f9167c734b3b1192cb0851b43d7cc08040c074c6279"}, + {file = "MarkupSafe-2.1.4-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:765f036a3d00395a326df2835d8f86b637dbaf9832f90f5d196c3b8a7a5080cb"}, + {file = "MarkupSafe-2.1.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:21e7af8091007bf4bebf4521184f4880a6acab8df0df52ef9e513d8e5db23411"}, + {file = "MarkupSafe-2.1.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d5c31fe855c77cad679b302aabc42d724ed87c043b1432d457f4976add1c2c3e"}, + {file = "MarkupSafe-2.1.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7653fa39578957bc42e5ebc15cf4361d9e0ee4b702d7d5ec96cdac860953c5b4"}, + {file = "MarkupSafe-2.1.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:47bb5f0142b8b64ed1399b6b60f700a580335c8e1c57f2f15587bd072012decc"}, + {file = "MarkupSafe-2.1.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:fe8512ed897d5daf089e5bd010c3dc03bb1bdae00b35588c49b98268d4a01e00"}, + {file = "MarkupSafe-2.1.4-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:36d7626a8cca4d34216875aee5a1d3d654bb3dac201c1c003d182283e3205949"}, + {file = "MarkupSafe-2.1.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:b6f14a9cd50c3cb100eb94b3273131c80d102e19bb20253ac7bd7336118a673a"}, + {file = "MarkupSafe-2.1.4-cp39-cp39-win32.whl", hash = "sha256:c8f253a84dbd2c63c19590fa86a032ef3d8cc18923b8049d91bcdeeb2581fbf6"}, + {file = "MarkupSafe-2.1.4-cp39-cp39-win_amd64.whl", hash = "sha256:8b570a1537367b52396e53325769608f2a687ec9a4363647af1cded8928af959"}, + {file = "MarkupSafe-2.1.4.tar.gz", hash = "sha256:3aae9af4cac263007fd6309c64c6ab4506dd2b79382d9d19a1994f9240b8db4f"}, ] [[package]] @@ -1789,13 +1796,13 @@ test = ["pep440", "pre-commit", "pytest", "testpath"] [[package]] name = "nest-asyncio" -version = "1.5.9" +version = "1.6.0" description = "Patch asyncio to allow nested event loops" optional = false python-versions = ">=3.5" files = [ - {file = "nest_asyncio-1.5.9-py3-none-any.whl", hash = "sha256:61ec07ef052e72e3de22045b81b2cc7d71fceb04c568ba0b2e4b2f9f5231bec2"}, - {file = "nest_asyncio-1.5.9.tar.gz", hash = "sha256:d1e1144e9c6e3e6392e0fcf5211cb1c8374b5648a98f1ebe48e5336006b41907"}, + {file = "nest_asyncio-1.6.0-py3-none-any.whl", hash = "sha256:87af6efd6b5e897c81050477ef65c62e2b2f35d51703cae01aff2905b1852e1c"}, + {file = "nest_asyncio-1.6.0.tar.gz", hash = "sha256:6f172d5449aca15afd6c646851f4e31e02c598d553a667e38cafa997cfec55fe"}, ] [[package]] @@ -1853,13 +1860,13 @@ full = ["XLMMacroDeobfuscator"] [[package]] name = "overrides" -version = "7.4.0" +version = "7.6.0" description = "A decorator to automatically detect mismatch when overriding a method." optional = false python-versions = ">=3.6" files = [ - {file = "overrides-7.4.0-py3-none-any.whl", hash = "sha256:3ad24583f86d6d7a49049695efe9933e67ba62f0c7625d53c59fa832ce4b8b7d"}, - {file = "overrides-7.4.0.tar.gz", hash = "sha256:9502a3cca51f4fac40b5feca985b6703a5c1f6ad815588a7ca9e285b9dca6757"}, + {file = "overrides-7.6.0-py3-none-any.whl", hash = "sha256:c36e6635519ea9c5b043b65c36d4b886aee8bd45b7d4681d2a6df0898df4b654"}, + {file = "overrides-7.6.0.tar.gz", hash = "sha256:01e15bbbf15b766f0675c275baa1878bd1c7dc9bc7b9ee13e677cdba93dc1bd9"}, ] [[package]] @@ -2095,27 +2102,27 @@ wcwidth = "*" [[package]] name = "psutil" -version = "5.9.7" +version = "5.9.8" description = "Cross-platform lib for process and system monitoring in Python." optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" files = [ - {file = "psutil-5.9.7-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:0bd41bf2d1463dfa535942b2a8f0e958acf6607ac0be52265ab31f7923bcd5e6"}, - {file = "psutil-5.9.7-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:5794944462509e49d4d458f4dbfb92c47539e7d8d15c796f141f474010084056"}, - {file = "psutil-5.9.7-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:fe361f743cb3389b8efda21980d93eb55c1f1e3898269bc9a2a1d0bb7b1f6508"}, - {file = "psutil-5.9.7-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:e469990e28f1ad738f65a42dcfc17adaed9d0f325d55047593cb9033a0ab63df"}, - {file = "psutil-5.9.7-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:3c4747a3e2ead1589e647e64aad601981f01b68f9398ddf94d01e3dc0d1e57c7"}, - {file = "psutil-5.9.7-cp27-none-win32.whl", hash = "sha256:1d4bc4a0148fdd7fd8f38e0498639ae128e64538faa507df25a20f8f7fb2341c"}, - {file = "psutil-5.9.7-cp27-none-win_amd64.whl", hash = "sha256:4c03362e280d06bbbfcd52f29acd79c733e0af33d707c54255d21029b8b32ba6"}, - {file = "psutil-5.9.7-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:ea36cc62e69a13ec52b2f625c27527f6e4479bca2b340b7a452af55b34fcbe2e"}, - {file = "psutil-5.9.7-cp36-abi3-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1132704b876e58d277168cd729d64750633d5ff0183acf5b3c986b8466cd0284"}, - {file = "psutil-5.9.7-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fe8b7f07948f1304497ce4f4684881250cd859b16d06a1dc4d7941eeb6233bfe"}, - {file = "psutil-5.9.7-cp36-cp36m-win32.whl", hash = "sha256:b27f8fdb190c8c03914f908a4555159327d7481dac2f01008d483137ef3311a9"}, - {file = "psutil-5.9.7-cp36-cp36m-win_amd64.whl", hash = "sha256:44969859757f4d8f2a9bd5b76eba8c3099a2c8cf3992ff62144061e39ba8568e"}, - {file = "psutil-5.9.7-cp37-abi3-win32.whl", hash = "sha256:c727ca5a9b2dd5193b8644b9f0c883d54f1248310023b5ad3e92036c5e2ada68"}, - {file = "psutil-5.9.7-cp37-abi3-win_amd64.whl", hash = "sha256:f37f87e4d73b79e6c5e749440c3113b81d1ee7d26f21c19c47371ddea834f414"}, - {file = "psutil-5.9.7-cp38-abi3-macosx_11_0_arm64.whl", hash = "sha256:032f4f2c909818c86cea4fe2cc407f1c0f0cde8e6c6d702b28b8ce0c0d143340"}, - {file = "psutil-5.9.7.tar.gz", hash = "sha256:3f02134e82cfb5d089fddf20bb2e03fd5cd52395321d1c8458a9e58500ff417c"}, + {file = "psutil-5.9.8-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:26bd09967ae00920df88e0352a91cff1a78f8d69b3ecabbfe733610c0af486c8"}, + {file = "psutil-5.9.8-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:05806de88103b25903dff19bb6692bd2e714ccf9e668d050d144012055cbca73"}, + {file = "psutil-5.9.8-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:611052c4bc70432ec770d5d54f64206aa7203a101ec273a0cd82418c86503bb7"}, + {file = "psutil-5.9.8-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:50187900d73c1381ba1454cf40308c2bf6f34268518b3f36a9b663ca87e65e36"}, + {file = "psutil-5.9.8-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:02615ed8c5ea222323408ceba16c60e99c3f91639b07da6373fb7e6539abc56d"}, + {file = "psutil-5.9.8-cp27-none-win32.whl", hash = "sha256:36f435891adb138ed3c9e58c6af3e2e6ca9ac2f365efe1f9cfef2794e6c93b4e"}, + {file = "psutil-5.9.8-cp27-none-win_amd64.whl", hash = "sha256:bd1184ceb3f87651a67b2708d4c3338e9b10c5df903f2e3776b62303b26cb631"}, + {file = "psutil-5.9.8-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:aee678c8720623dc456fa20659af736241f575d79429a0e5e9cf88ae0605cc81"}, + {file = "psutil-5.9.8-cp36-abi3-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8cb6403ce6d8e047495a701dc7c5bd788add903f8986d523e3e20b98b733e421"}, + {file = "psutil-5.9.8-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d06016f7f8625a1825ba3732081d77c94589dca78b7a3fc072194851e88461a4"}, + {file = "psutil-5.9.8-cp36-cp36m-win32.whl", hash = "sha256:7d79560ad97af658a0f6adfef8b834b53f64746d45b403f225b85c5c2c140eee"}, + {file = "psutil-5.9.8-cp36-cp36m-win_amd64.whl", hash = "sha256:27cc40c3493bb10de1be4b3f07cae4c010ce715290a5be22b98493509c6299e2"}, + {file = "psutil-5.9.8-cp37-abi3-win32.whl", hash = "sha256:bc56c2a1b0d15aa3eaa5a60c9f3f8e3e565303b465dbf57a1b730e7a2b9844e0"}, + {file = "psutil-5.9.8-cp37-abi3-win_amd64.whl", hash = "sha256:8db4c1b57507eef143a15a6884ca10f7c73876cdf5d51e713151c1236a0e68cf"}, + {file = "psutil-5.9.8-cp38-abi3-macosx_11_0_arm64.whl", hash = "sha256:d16bbddf0693323b8c6123dd804100241da461e41d6e332fb0ba6058f630f8c8"}, + {file = "psutil-5.9.8.tar.gz", hash = "sha256:6be126e3225486dff286a8fb9a06246a5253f4c7c53b475ea5f5ac934e64194c"}, ] [package.extras] @@ -3580,4 +3587,4 @@ virustotal = ["validators"] [metadata] lock-version = "2.0" python-versions = "^3.8" -content-hash = "fcf4e884ba74ca8562dc557ddc5270888f57f1e34dd773de9825c0f3e6e5f4c8" +content-hash = "fe53909337a8385381a72ee1b604ceaa0555946014ee34b5f1db4571d46299a1" diff --git a/pyproject.toml b/pyproject.toml index f42ac2d..cc9dd58 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -21,6 +21,7 @@ classifiers=[ 'Programming Language :: Python :: 3.9', 'Programming Language :: Python :: 3.10', 'Programming Language :: Python :: 3.11', + 'Programming Language :: Python :: 3.12', 'Topic :: Security', 'Topic :: Internet' ] @@ -49,7 +50,7 @@ RTFDE = {version = "^0.1.1", optional = true} oletools = {version = "^0.60.1", optional = true} python-magic = {version = "^0.4.27", optional = true} pydeep2 = {version = "^0.5.1", optional = true} -lief = {version = "^0.13.2", optional = true} +lief = {version = "^0.14", optional = true} beautifulsoup4 = {version = "^4.12.3", optional = true} validators = {version = "^0.22.0", optional = true} sphinx-autodoc-typehints = {version = "^1.25.2", optional = true} @@ -81,7 +82,7 @@ ipython = [ {version = "^8.18.0", python = ">=3.9"}, {version = "^8.19.0", python = ">=3.10"} ] -jupyterlab = "^4.0.10" +jupyterlab = "^4.0.11" types-requests = "^2.31.0.20240106" types-python-dateutil = "^2.8.19.20240106" types-redis = "^4.6.0.20240106" From 3a74ca87047420f1b4007f203472db9c0ec5a13d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Vinot?= Date: Mon, 22 Jan 2024 13:45:25 +0100 Subject: [PATCH 45/80] chg: Update typing to please lief --- pymisp/tools/create_misp_object.py | 13 ++++++++----- pymisp/tools/elfobject.py | 7 ++++--- pymisp/tools/fileobject.py | 3 +-- pymisp/tools/machoobject.py | 9 +++++---- pymisp/tools/peobject.py | 7 ++++--- 5 files changed, 22 insertions(+), 17 deletions(-) diff --git a/pymisp/tools/create_misp_object.py b/pymisp/tools/create_misp_object.py index 7864905..7c2a181 100644 --- a/pymisp/tools/create_misp_object.py +++ b/pymisp/tools/create_misp_object.py @@ -7,12 +7,12 @@ from io import BytesIO from . import FileObject from ..exceptions import MISPObjectException import logging -from typing import Optional logger = logging.getLogger('pymisp') try: import lief + import lief.logging lief.logging.disable() HAS_LIEF = True @@ -32,14 +32,17 @@ class FileTypeNotImplemented(MISPObjectException): pass -def make_binary_objects(filepath: str | None = None, pseudofile: BytesIO | None = None, filename: str | None = None, standalone: bool = True, default_attributes_parameters: dict = {}): +def make_binary_objects(filepath: str | None = None, pseudofile: BytesIO | bytes | None = None, filename: str | None = None, standalone: bool = True, default_attributes_parameters: dict = {}): misp_file = FileObject(filepath=filepath, pseudofile=pseudofile, filename=filename, standalone=standalone, default_attributes_parameters=default_attributes_parameters) - if HAS_LIEF and (filepath or (pseudofile and filename)): + if HAS_LIEF and (filepath or pseudofile): if filepath: lief_parsed = lief.parse(filepath=filepath) - elif pseudofile and filename: - lief_parsed = lief.parse(raw=pseudofile.getvalue(), name=filename) + elif pseudofile: + if isinstance(pseudofile, bytes): + lief_parsed = lief.parse(raw=pseudofile) + else: # BytesIO + lief_parsed = lief.parse(obj=pseudofile) else: logger.critical('You need either a filepath, or a pseudofile and a filename.') lief_parsed = None diff --git a/pymisp/tools/elfobject.py b/pymisp/tools/elfobject.py index 664bc83..80ad7c8 100644 --- a/pymisp/tools/elfobject.py +++ b/pymisp/tools/elfobject.py @@ -7,7 +7,6 @@ from ..exceptions import InvalidMISPObject from io import BytesIO from hashlib import md5, sha1, sha256, sha512 import logging -from typing import Union, Optional from pathlib import Path from . import FileObject @@ -33,15 +32,17 @@ def make_elf_objects(lief_parsed: lief.ELF.Binary, misp_file: FileObject, standa class ELFObject(AbstractMISPObjectGenerator): - def __init__(self, parsed: lief.ELF.Binary | None = None, filepath: Path | str | None = None, pseudofile: BytesIO | None = None, **kwargs): + def __init__(self, parsed: lief.ELF.Binary | None = None, filepath: Path | str | None = None, pseudofile: BytesIO | bytes | list[int] | None = None, **kwargs): """Creates an ELF object, with lief""" super().__init__('elf', **kwargs) if not HAS_PYDEEP: logger.warning("pydeep is missing, please install pymisp this way: pip install pymisp[fileobjects]") if pseudofile: if isinstance(pseudofile, BytesIO): - self.__elf = lief.ELF.parse(io=pseudofile) + self.__elf = lief.ELF.parse(obj=pseudofile) elif isinstance(pseudofile, bytes): + self.__elf = lief.ELF.parse(raw=list(pseudofile)) + elif isinstance(pseudofile, list): self.__elf = lief.ELF.parse(raw=pseudofile) else: raise InvalidMISPObject(f'Pseudo file can be BytesIO or bytes got {type(pseudofile)}') diff --git a/pymisp/tools/fileobject.py b/pymisp/tools/fileobject.py index 696eeed..9a8c8be 100644 --- a/pymisp/tools/fileobject.py +++ b/pymisp/tools/fileobject.py @@ -11,7 +11,6 @@ import math from collections import Counter import logging from pathlib import Path -from typing import Union, Optional logger = logging.getLogger('pymisp') @@ -31,7 +30,7 @@ except ImportError: class FileObject(AbstractMISPObjectGenerator): - def __init__(self, filepath: Path | str | None = None, pseudofile: BytesIO | None = None, filename: str | None = None, **kwargs) -> None: + def __init__(self, filepath: Path | str | None = None, pseudofile: BytesIO | bytes | None = None, filename: str | None = None, **kwargs) -> None: super().__init__('file', **kwargs) if not HAS_PYDEEP: logger.warning("pydeep is missing, please install pymisp this way: pip install pymisp[fileobjects]") diff --git a/pymisp/tools/machoobject.py b/pymisp/tools/machoobject.py index 4a71db4..58f2e70 100644 --- a/pymisp/tools/machoobject.py +++ b/pymisp/tools/machoobject.py @@ -7,7 +7,6 @@ from .abstractgenerator import AbstractMISPObjectGenerator from io import BytesIO from hashlib import md5, sha1, sha256, sha512 import logging -from typing import Optional, Union from pathlib import Path from . import FileObject @@ -33,15 +32,17 @@ def make_macho_objects(lief_parsed: lief.MachO.Binary, misp_file: FileObject, st class MachOObject(AbstractMISPObjectGenerator): - def __init__(self, parsed: lief.MachO.Binary | None = None, filepath: Path | str | None = None, pseudofile: BytesIO | None = None, **kwargs): + def __init__(self, parsed: lief.MachO.Binary | None = None, filepath: Path | str | None = None, pseudofile: BytesIO | list[int] | None = None, **kwargs): """Creates an MachO object, with lief""" super().__init__('macho', **kwargs) if not HAS_PYDEEP: logger.warning("pydeep is missing, please install pymisp this way: pip install pymisp[fileobjects]") if pseudofile: if isinstance(pseudofile, BytesIO): - self.__macho = lief.MachO.parse(io=pseudofile) + self.__macho = lief.MachO.parse(obj=pseudofile) elif isinstance(pseudofile, bytes): + self.__macho = lief.MachO.parse(raw=list(pseudofile)) + elif isinstance(pseudofile, list): self.__macho = lief.MachO.parse(raw=pseudofile) else: raise InvalidMISPObject(f'Pseudo file can be BytesIO or bytes got {type(pseudofile)}') @@ -49,7 +50,7 @@ class MachOObject(AbstractMISPObjectGenerator): self.__macho = lief.MachO.parse(filepath) elif parsed: # Got an already parsed blob - if isinstance(parsed, lief.MachO.Binary): + if isinstance(parsed, lief.MachO.FatBinary): self.__macho = parsed else: raise InvalidMISPObject(f'Not a lief.MachO.Binary: {type(parsed)}') diff --git a/pymisp/tools/peobject.py b/pymisp/tools/peobject.py index 151ed3b..92b3ff8 100644 --- a/pymisp/tools/peobject.py +++ b/pymisp/tools/peobject.py @@ -8,7 +8,6 @@ from io import BytesIO from hashlib import md5, sha1, sha256, sha512 from datetime import datetime import logging -from typing import Optional, Union from pathlib import Path from base64 import b64encode @@ -36,15 +35,17 @@ def make_pe_objects(lief_parsed: lief.PE.Binary, misp_file: FileObject, standalo class PEObject(AbstractMISPObjectGenerator): - def __init__(self, parsed: lief.PE.Binary | None = None, filepath: Path | str | None = None, pseudofile: BytesIO | None = None, **kwargs): + def __init__(self, parsed: lief.PE.Binary | None = None, filepath: Path | str | None = None, pseudofile: BytesIO | list[int] | None = None, **kwargs): """Creates an PE object, with lief""" super().__init__('pe', **kwargs) if not HAS_PYDEEP: logger.warning("pydeep is missing, please install pymisp this way: pip install pymisp[fileobjects]") if pseudofile: if isinstance(pseudofile, BytesIO): - self.__pe = lief.PE.parse(io=pseudofile) + self.__pe = lief.PE.parse(obj=pseudofile) elif isinstance(pseudofile, bytes): + self.__pe = lief.PE.parse(raw=list(pseudofile)) + elif isinstance(pseudofile, list): self.__pe = lief.PE.parse(raw=pseudofile) else: raise InvalidMISPObject(f'Pseudo file can be BytesIO or bytes got {type(pseudofile)}') From 298e2f90354b385ba24087680320457e35af97fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Vinot?= Date: Tue, 30 Jan 2024 12:51:23 +0100 Subject: [PATCH 46/80] chg: First batch of changes for strict typing --- mypy.ini | 6 +- pymisp/__init__.py | 16 +- pymisp/abstract.py | 68 ++-- pymisp/api.py | 574 +++++++++++++++--------------- pymisp/exceptions.py | 2 +- pymisp/mispevent.py | 449 ++++++++++------------- pymisp/tools/__init__.py | 10 + pymisp/tools/abstractgenerator.py | 1 - pymisp/tools/asnobject.py | 7 +- tests/testlive_sync.py | 13 +- 10 files changed, 552 insertions(+), 594 deletions(-) diff --git a/mypy.ini b/mypy.ini index 9c8481b..0351d61 100644 --- a/mypy.ini +++ b/mypy.ini @@ -3,13 +3,11 @@ strict = True warn_return_any = False show_error_context = True pretty = True -exclude = feed-generator|examples +exclude = feed-generator|examples|pymisp/tools|pymisp/data|tests # Stuff to remove gradually -disallow_untyped_defs = False +# disallow_untyped_defs = False disallow_untyped_calls = False -check_untyped_defs = False -disable_error_code = attr-defined,type-arg,no-untyped-def [mypy-docs.source.*] diff --git a/pymisp/__init__.py b/pymisp/__init__.py index a38ad3c..9599bdc 100644 --- a/pymisp/__init__.py +++ b/pymisp/__init__.py @@ -11,7 +11,7 @@ logger = logging.getLogger(__name__) __version__ = importlib.metadata.version("pymisp") -def warning_2024(): +def warning_2024() -> None: if sys.version_info < (3, 10): warnings.warn(""" As our baseline system is the latest Ubuntu LTS, and Ubuntu LTS 22.04 has Python 3.10 available, @@ -62,3 +62,17 @@ try: logger.debug('pymisp loaded properly') except ImportError as e: logger.warning(f'Unable to load pymisp properly: {e}') + +__all__ = ['PyMISP', 'register_user', 'AbstractMISP', 'MISPTag', + 'MISPEvent', 'MISPAttribute', 'MISPObjectReference', 'MISPObjectAttribute', + 'MISPObject', 'MISPUser', 'MISPOrganisation', 'MISPSighting', 'MISPLog', + 'MISPShadowAttribute', 'MISPWarninglist', 'MISPTaxonomy', 'MISPNoticelist', + 'MISPObjectTemplate', 'MISPSharingGroup', 'MISPRole', 'MISPServer', 'MISPFeed', + 'MISPEventDelegation', 'MISPUserSetting', 'MISPInbox', 'MISPEventBlocklist', + 'MISPOrganisationBlocklist', 'MISPEventReport', 'MISPCorrelationExclusion', + 'MISPDecayingModel', 'MISPGalaxy', 'MISPGalaxyCluster', 'MISPGalaxyClusterElement', + 'MISPGalaxyClusterRelation', 'PyMISPError', 'NewEventError', 'NewAttributeError', + 'NoURL', 'NoKey', 'InvalidMISPObject', 'UnknownMISPObjectTemplate', 'PyMISPInvalidFormat', + 'EmailObject', 'FileObject', 'IPObject', 'DomainObject', 'URIObject', 'ASNObject', + 'Distribution', 'ThreatLevel', 'Analysis' + ] diff --git a/pymisp/abstract.py b/pymisp/abstract.py index 879079f..ec17e0f 100644 --- a/pymisp/abstract.py +++ b/pymisp/abstract.py @@ -30,7 +30,7 @@ logger = logging.getLogger('pymisp') resources_path = Path(__file__).parent / 'data' misp_objects_path = resources_path / 'misp-objects' / 'objects' with (resources_path / 'describeTypes.json').open('rb') as f: - describe_types = loads(f.read())['result'] + describe_types: dict[str, Any] = loads(f.read())['result'] class MISPFileCache: @@ -38,7 +38,7 @@ class MISPFileCache: @staticmethod @lru_cache(maxsize=150) - def _load_json(path: Path) -> dict | None: + def _load_json(path: Path) -> dict[str, Any] | None: if not path.exists(): return None with path.open('rb') as f: @@ -80,7 +80,7 @@ def _int_to_str(d: dict[str, Any]) -> dict[str, Any]: @deprecated(reason=" Use method default=pymisp_json_default instead of cls=MISPEncode", version='2.4.117', action='default') class MISPEncode(JSONEncoder): - def default(self, obj): + def default(self, obj: Any) -> dict[str, Any] | str: if isinstance(obj, AbstractMISP): return obj.jsonable() elif isinstance(obj, (datetime, date)): @@ -92,12 +92,12 @@ class MISPEncode(JSONEncoder): return JSONEncoder.default(self, obj) -class AbstractMISP(MutableMapping, MISPFileCache, metaclass=ABCMeta): +class AbstractMISP(MutableMapping[str, Any], MISPFileCache, metaclass=ABCMeta): __resources_path = resources_path __misp_objects_path = misp_objects_path __describe_types = describe_types - def __init__(self, **kwargs: dict): + def __init__(self, **kwargs) -> None: # type: ignore[no-untyped-def] """Abstract class for all the MISP objects. NOTE: Every method in every classes inheriting this one are doing changes in memory and do not modify data on a remote MISP instance. @@ -107,8 +107,8 @@ class AbstractMISP(MutableMapping, MISPFileCache, metaclass=ABCMeta): super().__init__() self.__edited: bool = True # As we create a new object, we assume it is edited self.__not_jsonable: list[str] = [] - self._fields_for_feed: set - self.__self_defined_describe_types: dict | None = None + self._fields_for_feed: set[str] + self.__self_defined_describe_types: dict[str, Any] | None = None self.uuid: str if kwargs.get('force_timestamps') is not None: @@ -118,13 +118,13 @@ class AbstractMISP(MutableMapping, MISPFileCache, metaclass=ABCMeta): self.__force_timestamps = False @property - def describe_types(self) -> dict: + def describe_types(self) -> dict[str, Any]: if self.__self_defined_describe_types: return self.__self_defined_describe_types return self.__describe_types @describe_types.setter - def describe_types(self, describe_types: dict): + def describe_types(self, describe_types: dict[str, Any]) -> None: self.__self_defined_describe_types = describe_types @property @@ -136,12 +136,12 @@ class AbstractMISP(MutableMapping, MISPFileCache, metaclass=ABCMeta): return self.__misp_objects_path @misp_objects_path.setter - def misp_objects_path(self, misp_objects_path: str | Path): + def misp_objects_path(self, misp_objects_path: str | Path) -> None: if isinstance(misp_objects_path, str): misp_objects_path = Path(misp_objects_path) self.__misp_objects_path = misp_objects_path - def from_dict(self, **kwargs) -> None: + def from_dict(self, **kwargs) -> None: # type: ignore[no-untyped-def] """Loading all the parameters as class properties, if they aren't `None`. This method aims to be called when all the properties requiring a special treatment are processed. @@ -154,7 +154,7 @@ class AbstractMISP(MutableMapping, MISPFileCache, metaclass=ABCMeta): # We load an existing dictionary, marking it an not-edited self.__edited = False - def update_not_jsonable(self, *args) -> None: + def update_not_jsonable(self, *args) -> None: # type: ignore[no-untyped-def] """Add entries to the __not_jsonable list""" self.__not_jsonable += args @@ -162,7 +162,7 @@ class AbstractMISP(MutableMapping, MISPFileCache, metaclass=ABCMeta): """Set __not_jsonable to a new list""" self.__not_jsonable = args - def _remove_from_not_jsonable(self, *args) -> None: + def _remove_from_not_jsonable(self, *args) -> None: # type: ignore[no-untyped-def] """Remove the entries that are in the __not_jsonable list""" for entry in args: try: @@ -174,7 +174,7 @@ class AbstractMISP(MutableMapping, MISPFileCache, metaclass=ABCMeta): """Load a JSON string""" self.from_dict(**loads(json_string)) - def to_dict(self, json_format: bool = False) -> dict: + def to_dict(self, json_format: bool = False) -> dict[str, Any]: """Dump the class to a dictionary. This method automatically removes the timestamp recursively in every object that has been edited is order to let MISP update the event accordingly.""" @@ -216,11 +216,11 @@ class AbstractMISP(MutableMapping, MISPFileCache, metaclass=ABCMeta): to_return = _int_to_str(to_return) return to_return - def jsonable(self) -> dict: + def jsonable(self) -> dict[str, Any]: """This method is used by the JSON encoder""" return self.to_dict() - def _to_feed(self) -> dict: + def _to_feed(self) -> dict[str, Any]: if not hasattr(self, '_fields_for_feed') or not self._fields_for_feed: raise PyMISPError('Unable to export in the feed format, _fields_for_feed is missing.') if hasattr(self, '_set_default') and callable(self._set_default): @@ -256,7 +256,7 @@ class AbstractMISP(MutableMapping, MISPFileCache, metaclass=ABCMeta): return dumps(self, default=pymisp_json_default, sort_keys=sort_keys, indent=indent) - def __getitem__(self, key): + def __getitem__(self, key: str) -> Any: try: if key[0] != '_' and key not in self.__not_jsonable: return self.__dict__[key] @@ -265,13 +265,13 @@ class AbstractMISP(MutableMapping, MISPFileCache, metaclass=ABCMeta): # Expected by pop and other dict-related methods raise KeyError - def __setitem__(self, key, value): + def __setitem__(self, key: str, value: Any) -> None: setattr(self, key, value) - def __delitem__(self, key): + def __delitem__(self, key: str) -> None: delattr(self, key) - def __iter__(self): + def __iter__(self) -> Any: '''When we call **self, skip keys: * starting with _ * in __not_jsonable @@ -290,7 +290,7 @@ class AbstractMISP(MutableMapping, MISPFileCache, metaclass=ABCMeta): return self.__force_timestamps @force_timestamp.setter - def force_timestamp(self, force: bool): + def force_timestamp(self, force: bool) -> None: self.__force_timestamps = force @property @@ -310,14 +310,14 @@ class AbstractMISP(MutableMapping, MISPFileCache, metaclass=ABCMeta): return self.__edited @edited.setter - def edited(self, val: bool): + def edited(self, val: bool) -> None: """Set the edit flag""" if isinstance(val, bool): self.__edited = val else: raise PyMISPError('edited can only be True or False') - def __setattr__(self, name: str, value: Any): + def __setattr__(self, name: str, value: Any) -> None: if name[0] != '_' and not self.__edited and name in self: # The private members don't matter # If we already have a key with that name, we're modifying it. @@ -331,7 +331,7 @@ class AbstractMISP(MutableMapping, MISPFileCache, metaclass=ABCMeta): return int(d) return int(d.timestamp()) - def _add_tag(self, tag: str | MISPTag | Mapping | None = None, **kwargs): + def _add_tag(self, tag: str | MISPTag | Mapping[str, Any] | None = None, **kwargs): # type: ignore[no-untyped-def] """Add a tag to the attribute (by name or a MISPTag object)""" if isinstance(tag, str): misp_tag = MISPTag() @@ -351,14 +351,14 @@ class AbstractMISP(MutableMapping, MISPFileCache, metaclass=ABCMeta): self.edited = True return misp_tag - def _set_tags(self, tags: list[MISPTag]): + def _set_tags(self, tags: list[MISPTag]) -> None: """Set a list of prepared MISPTag.""" if all(isinstance(x, MISPTag) for x in tags): self.Tag = tags else: raise PyMISPInvalidFormat('All the attributes have to be of type MISPTag.') - def __eq__(self, other) -> bool: + def __eq__(self, other: object) -> bool: if isinstance(other, AbstractMISP): return self.to_dict() == other.to_dict() elif isinstance(other, dict): @@ -372,21 +372,21 @@ class AbstractMISP(MutableMapping, MISPFileCache, metaclass=ABCMeta): class MISPTag(AbstractMISP): - _fields_for_feed: set = {'name', 'colour', 'relationship_type', 'local'} + _fields_for_feed: set[str] = {'name', 'colour', 'relationship_type', 'local'} - def __init__(self, **kwargs: dict): + def __init__(self, **kwargs) -> None: # type: ignore[no-untyped-def] super().__init__(**kwargs) self.name: str self.exportable: bool self.local: bool self.relationship_type: str | None - def from_dict(self, **kwargs): + def from_dict(self, **kwargs) -> None: # type: ignore[no-untyped-def] if kwargs.get('Tag'): - kwargs = kwargs.get('Tag') + kwargs = kwargs.get('Tag') # type: ignore[assignment] super().from_dict(**kwargs) - def _set_default(self): + def _set_default(self) -> None: if not hasattr(self, 'relationship_type'): self.relationship_type = '' if not hasattr(self, 'colour'): @@ -394,14 +394,14 @@ class MISPTag(AbstractMISP): if not hasattr(self, 'local'): self.local = False - def _to_feed(self, with_local: bool = True) -> dict: + def _to_feed(self, with_local: bool = True) -> dict[str, Any]: if hasattr(self, 'exportable') and not self.exportable: return {} if with_local is False and hasattr(self, 'local') and self.local: return {} return super()._to_feed() - def delete(self): + def delete(self) -> None: self.deleted = True self.edited = True @@ -412,7 +412,7 @@ class MISPTag(AbstractMISP): # UUID, datetime, date and Enum is serialized by ORJSON by default -def pymisp_json_default(obj: AbstractMISP | datetime | date | Enum | UUID) -> dict | str: +def pymisp_json_default(obj: AbstractMISP | datetime | date | Enum | UUID) -> dict[str, Any] | str: if isinstance(obj, AbstractMISP): return obj.jsonable() elif isinstance(obj, (datetime, date)): diff --git a/pymisp/api.py b/pymisp/api.py index 771f691..583239c 100644 --- a/pymisp/api.py +++ b/pymisp/api.py @@ -13,8 +13,8 @@ from uuid import UUID import warnings import sys import copy -import urllib3 from io import BytesIO, StringIO +from importlib.metadata import version try: # orjson is optional dependency that speedups parsing and encoding JSON @@ -64,7 +64,7 @@ ToIDSType = TypeVar('ToIDSType', str, int, bool) logger = logging.getLogger('pymisp') -def get_uuid_or_id_from_abstract_misp(obj: AbstractMISP | int | str | UUID | dict) -> str | int: +def get_uuid_or_id_from_abstract_misp(obj: AbstractMISP | int | str | UUID | dict[str, Any]) -> str | int: """Extract the relevant ID accordingly to the given type passed as parameter""" if isinstance(obj, UUID): return str(obj) @@ -100,7 +100,7 @@ def register_user(misp_url: str, email: str, org_id: str | None = None, org_name: str | None = None, message: str | None = None, custom_perms: str | None = None, perm_sync: bool = False, perm_publish: bool = False, perm_admin: bool = False, - verify: bool = True) -> dict: + verify: bool = True) -> dict[str, Any]: """Ask for the creation of an account for the user with the given email address""" data = copy.deepcopy(locals()) if organisation: @@ -125,7 +125,7 @@ def brotli_supported() -> bool: patch: int # urllib >= 1.25.1 includes brotli support - version_splitted = urllib3.__version__.split('.') # noqa: F811 + version_splitted = version('urllib3').split('.') # noqa: F811 if len(version_splitted) == 2: major, minor = version_splitted # type: ignore patch = 0 @@ -224,7 +224,7 @@ class PyMISP: if e := user_infos.get('errors'): raise PyMISPError(f'Unable to get the user settings: {e}') raise PyMISPError(f'Unexpected error when initializing the connection: {user_infos}') - elif len(user_infos) == 3: + elif isinstance(user_infos, tuple) and len(user_infos) == 3: self._current_user, self._current_role, self._current_user_settings = user_infos else: raise PyMISPError(f'Unexpected error when initializing the connection: {user_infos}') @@ -243,7 +243,7 @@ class PyMISP: self.category_type_mapping = self.describe_types['category_type_mappings'] self.sane_default = self.describe_types['sane_defaults'] - def remote_acl(self, debug_type: str = 'findMissingFunctionNames') -> dict: + def remote_acl(self, debug_type: str = 'findMissingFunctionNames') -> dict[str, Any]: """This should return an empty list, unless the ACL is outdated. :param debug_type: printAllFunctionNames, findMissingFunctionNames, or printRoleAccess @@ -252,19 +252,19 @@ class PyMISP: return self._check_json_response(response) @property - def describe_types_local(self) -> dict: + def describe_types_local(self) -> dict[str, Any]: '''Returns the content of describe types from the package''' return describe_types @property - def describe_types_remote(self) -> dict: + def describe_types_remote(self) -> dict[str, Any]: '''Returns the content of describe types from the remote instance''' response = self._prepare_request('GET', 'attributes/describeTypes.json') remote_describe_types = self._check_json_response(response) return remote_describe_types['result'] @property - def recommended_pymisp_version(self) -> dict: + def recommended_pymisp_version(self) -> dict[str, Any]: """Returns the recommended API version from the server""" # Sine MISP 2.4.146 is recommended PyMISP version included in getVersion call misp_version = self.misp_instance_version @@ -275,17 +275,17 @@ class PyMISP: return self._check_json_response(response) @property - def version(self) -> dict: + def version(self) -> dict[str, Any]: """Returns the version of PyMISP you're currently using""" return {'version': __version__} @property - def pymisp_version_master(self) -> dict: + def pymisp_version_master(self) -> dict[str, Any]: """PyMISP version as defined in the main repository""" return self.pymisp_version_main @property - def pymisp_version_main(self) -> dict: + def pymisp_version_main(self) -> dict[str, Any]: """Get the most recent version of PyMISP from github""" r = requests.get('https://raw.githubusercontent.com/MISP/PyMISP/main/pyproject.toml') if r.status_code == 200: @@ -294,13 +294,13 @@ class PyMISP: return {'error': 'Impossible to retrieve the version of the main branch.'} @cached_property - def misp_instance_version(self) -> dict: + def misp_instance_version(self) -> dict[str, Any]: """Returns the version of the instance.""" response = self._prepare_request('GET', 'servers/getVersion') return self._check_json_response(response) @property - def misp_instance_version_master(self) -> dict: + def misp_instance_version_master(self) -> dict[str, Any]: """Get the most recent version from github""" r = requests.get('https://raw.githubusercontent.com/MISP/MISP/2.4/VERSION.json') if r.status_code == 200: @@ -308,12 +308,12 @@ class PyMISP: return {'version': '{}.{}.{}'.format(master_version['major'], master_version['minor'], master_version['hotfix'])} return {'error': 'Impossible to retrieve the version of the master branch.'} - def update_misp(self) -> dict: + def update_misp(self) -> dict[str, Any]: """Trigger a server update""" response = self._prepare_request('POST', 'servers/update') return self._check_json_response(response) - def set_server_setting(self, setting: str, value: str | int | bool, force: bool = False) -> dict: + def set_server_setting(self, setting: str, value: str | int | bool, force: bool = False) -> dict[str, Any]: """Set a setting on the MISP instance :param setting: server setting name @@ -324,7 +324,7 @@ class PyMISP: response = self._prepare_request('POST', f'servers/serverSettingsEdit/{setting}', data=data) return self._check_json_response(response) - def get_server_setting(self, setting: str) -> dict: + def get_server_setting(self, setting: str) -> dict[str, Any]: """Get a setting from the MISP instance :param setting: server setting name @@ -332,17 +332,17 @@ class PyMISP: response = self._prepare_request('GET', f'servers/getSetting/{setting}') return self._check_json_response(response) - def server_settings(self) -> dict: + def server_settings(self) -> dict[str, Any]: """Get all the settings from the server""" response = self._prepare_request('GET', 'servers/serverSettings') return self._check_json_response(response) - def restart_workers(self) -> dict: + def restart_workers(self) -> dict[str, Any]: """Restart all the workers""" response = self._prepare_request('POST', 'servers/restartWorkers') return self._check_json_response(response) - def db_schema_diagnostic(self) -> dict: + def db_schema_diagnostic(self) -> dict[str, Any]: """Get the schema diagnostic""" response = self._prepare_request('GET', 'servers/dbSchemaDiagnostic') return self._check_json_response(response) @@ -353,14 +353,14 @@ class PyMISP: # ## BEGIN Event ## - def events(self, pythonify: bool = False) -> dict | list[MISPEvent]: + def events(self, pythonify: bool = False) -> dict[str, Any] | list[MISPEvent] | list[dict[str, Any]]: """Get all the events from the MISP instance: https://www.misp-project.org/openapi/#tag/Events/operation/getEvents :param pythonify: Returns a list of PyMISP Objects instead of the plain json output. Warning: it might use a lot of RAM """ r = self._prepare_request('GET', 'events/index') - events_r = self._check_json_response(r) - if not (self.global_pythonify or pythonify) or 'errors' in events_r: + events_r = self._check_json_response_list(r) + if not (self.global_pythonify or pythonify) or isinstance(events_r, dict): return events_r to_return = [] for event in events_r: @@ -370,9 +370,9 @@ class PyMISP: return to_return def get_event(self, event: MISPEvent | int | str | UUID, - deleted: bool | int | list = False, + deleted: bool | int | list[int] = False, extended: bool | int = False, - pythonify: bool = False) -> dict | MISPEvent: + pythonify: bool = False) -> dict[str, Any] | MISPEvent: """Get an event from a MISP instance. Includes collections like Attribute, EventReport, Feed, Galaxy, Object, Tag, etc. so the response size may be large : https://www.misp-project.org/openapi/#tag/Events/operation/getEventById @@ -408,7 +408,7 @@ class PyMISP: r = self._prepare_request('HEAD', f'events/view/{event_id}') return self._check_head_response(r) - def add_event(self, event: MISPEvent, pythonify: bool = False, metadata: bool = False) -> dict | MISPEvent: + def add_event(self, event: MISPEvent, pythonify: bool = False, metadata: bool = False) -> dict[str, Any] | MISPEvent: """Add a new event on a MISP instance: https://www.misp-project.org/openapi/#tag/Events/operation/addEvent :param event: event to add @@ -424,7 +424,7 @@ class PyMISP: return e def update_event(self, event: MISPEvent, event_id: int | None = None, pythonify: bool = False, - metadata: bool = False) -> dict | MISPEvent: + metadata: bool = False) -> dict[str, Any] | MISPEvent: """Update an event on a MISP instance: https://www.misp-project.org/openapi/#tag/Events/operation/editEvent :param event: event to update @@ -444,7 +444,7 @@ class PyMISP: e.load(updated_event) return e - def delete_event(self, event: MISPEvent | int | str | UUID) -> dict: + def delete_event(self, event: MISPEvent | int | str | UUID) -> dict[str, Any]: """Delete an event from a MISP instance: https://www.misp-project.org/openapi/#tag/Events/operation/deleteEvent :param event: event to delete @@ -453,7 +453,7 @@ class PyMISP: response = self._prepare_request('POST', f'events/delete/{event_id}') return self._check_json_response(response) - def publish(self, event: MISPEvent | int | str | UUID, alert: bool = False) -> dict: + def publish(self, event: MISPEvent | int | str | UUID, alert: bool = False) -> dict[str, Any]: """Publish the event with one single HTTP POST: https://www.misp-project.org/openapi/#tag/Events/operation/publishEvent :param event: event to publish @@ -466,7 +466,7 @@ class PyMISP: response = self._prepare_request('POST', f'events/publish/{event_id}') return self._check_json_response(response) - def unpublish(self, event: MISPEvent | int | str | UUID) -> dict: + def unpublish(self, event: MISPEvent | int | str | UUID) -> dict[str, Any]: """Unpublish the event with one single HTTP POST: https://www.misp-project.org/openapi/#tag/Events/operation/unpublishEvent :param event: event to unpublish @@ -475,7 +475,7 @@ class PyMISP: response = self._prepare_request('POST', f'events/unpublish/{event_id}') return self._check_json_response(response) - def contact_event_reporter(self, event: MISPEvent | int | str | UUID, message: str) -> dict: + def contact_event_reporter(self, event: MISPEvent | int | str | UUID, message: str) -> dict[str, Any]: """Send a message to the reporter of an event :param event: event with reporter to contact @@ -491,7 +491,7 @@ class PyMISP: # ## BEGIN Event Report ### def get_event_report(self, event_report: MISPEventReport | int | str | UUID, - pythonify: bool = False) -> dict | MISPEventReport: + pythonify: bool = False) -> dict[str, Any] | MISPEventReport: """Get an event report from a MISP instance :param event_report: event report to get @@ -507,15 +507,15 @@ class PyMISP: return er def get_event_reports(self, event_id: int | str, - pythonify: bool = False) -> dict | list[MISPEventReport]: + pythonify: bool = False) -> dict[str, Any] | list[MISPEventReport] | list[dict[str, Any]]: """Get event report from a MISP instance that are attached to an event ID :param event_id: event id to get the event reports for :param pythonify: Returns a list of PyMISP Objects instead of the plain json output. """ r = self._prepare_request('GET', f'eventReports/index/event_id:{event_id}') - event_reports = self._check_json_response(r) - if not (self.global_pythonify or pythonify) or 'errors' in event_reports: + event_reports = self._check_json_response_list(r) + if not (self.global_pythonify or pythonify) or isinstance(event_reports, dict): return event_reports to_return = [] for event_report in event_reports: @@ -524,7 +524,7 @@ class PyMISP: to_return.append(er) return to_return - def add_event_report(self, event: MISPEvent | int | str | UUID, event_report: MISPEventReport, pythonify: bool = False) -> dict | MISPEventReport: + def add_event_report(self, event: MISPEvent | int | str | UUID, event_report: MISPEventReport, pythonify: bool = False) -> dict[str, Any] | MISPEventReport: """Add an event report to an existing MISP event :param event: event to extend @@ -540,7 +540,7 @@ class PyMISP: er.from_dict(**new_event_report) return er - def update_event_report(self, event_report: MISPEventReport, event_report_id: int | None = None, pythonify: bool = False) -> dict | MISPEventReport: + def update_event_report(self, event_report: MISPEventReport, event_report_id: int | None = None, pythonify: bool = False) -> dict[str, Any] | MISPEventReport: """Update an event report on a MISP instance :param event_report: event report to update @@ -559,7 +559,7 @@ class PyMISP: er.from_dict(**updated_event_report) return er - def delete_event_report(self, event_report: MISPEventReport | int | str | UUID, hard: bool = False) -> dict: + def delete_event_report(self, event_report: MISPEventReport | int | str | UUID, hard: bool = False) -> dict[str, Any]: """Delete an event report from a MISP instance :param event_report: event report to delete @@ -577,7 +577,7 @@ class PyMISP: # ## BEGIN Object ### - def get_object(self, misp_object: MISPObject | int | str | UUID, pythonify: bool = False) -> dict | MISPObject: + def get_object(self, misp_object: MISPObject | int | str | UUID, pythonify: bool = False) -> dict[str, Any] | MISPObject: """Get an object from the remote MISP instance: https://www.misp-project.org/openapi/#tag/Objects/operation/getObjectById :param misp_object: object to get @@ -601,7 +601,7 @@ class PyMISP: r = self._prepare_request('HEAD', f'objects/view/{object_id}') return self._check_head_response(r) - def add_object(self, event: MISPEvent | int | str | UUID, misp_object: MISPObject, pythonify: bool = False, break_on_duplicate: bool = False) -> dict | MISPObject: + def add_object(self, event: MISPEvent | int | str | UUID, misp_object: MISPObject, pythonify: bool = False, break_on_duplicate: bool = False) -> dict[str, Any] | MISPObject: """Add a MISP Object to an existing MISP event: https://www.misp-project.org/openapi/#tag/Objects/operation/addObject :param event: event to extend @@ -619,7 +619,7 @@ class PyMISP: o.from_dict(**new_object) return o - def update_object(self, misp_object: MISPObject, object_id: int | None = None, pythonify: bool = False) -> dict | MISPObject: + def update_object(self, misp_object: MISPObject, object_id: int | None = None, pythonify: bool = False) -> dict[str, Any] | MISPObject: """Update an object on a MISP instance :param misp_object: object to update @@ -638,7 +638,7 @@ class PyMISP: o.from_dict(**updated_object) return o - def delete_object(self, misp_object: MISPObject | int | str | UUID, hard: bool = False) -> dict: + def delete_object(self, misp_object: MISPObject | int | str | UUID, hard: bool = False) -> dict[str, Any]: """Delete an object from a MISP instance: https://www.misp-project.org/openapi/#tag/Objects/operation/deleteObject :param misp_object: object to delete @@ -651,7 +651,7 @@ class PyMISP: r = self._prepare_request('POST', f'objects/delete/{object_id}', data=data) return self._check_json_response(r) - def add_object_reference(self, misp_object_reference: MISPObjectReference, pythonify: bool = False) -> dict | MISPObjectReference: + def add_object_reference(self, misp_object_reference: MISPObjectReference, pythonify: bool = False) -> dict[str, Any] | MISPObjectReference: """Add a reference to an object :param misp_object_reference: object reference @@ -669,7 +669,7 @@ class PyMISP: self, object_reference: MISPObjectReference | int | str | UUID, hard: bool = False, - ) -> dict: + ) -> dict[str, Any]: """Delete a reference to an object.""" object_reference_id = get_uuid_or_id_from_abstract_misp(object_reference) query_url = f"objectReferences/delete/{object_reference_id}" @@ -680,14 +680,14 @@ class PyMISP: # Object templates - def object_templates(self, pythonify: bool = False) -> dict | list[MISPObjectTemplate]: + def object_templates(self, pythonify: bool = False) -> dict[str, Any] | list[MISPObjectTemplate] | list[dict[str, Any]]: """Get all the object templates :param pythonify: Returns a list of PyMISP Objects instead of the plain json output. Warning: it might use a lot of RAM """ r = self._prepare_request('GET', 'objectTemplates/index') - templates = self._check_json_response(r) - if not (self.global_pythonify or pythonify) or 'errors' in templates: + templates = self._check_json_response_list(r) + if not (self.global_pythonify or pythonify) or isinstance(templates, dict): return templates to_return = [] for object_template in templates: @@ -696,7 +696,7 @@ class PyMISP: to_return.append(o) return to_return - def get_object_template(self, object_template: MISPObjectTemplate | int | str | UUID, pythonify: bool = False) -> dict | MISPObjectTemplate: + def get_object_template(self, object_template: MISPObjectTemplate | int | str | UUID, pythonify: bool = False) -> dict[str, Any] | MISPObjectTemplate: """Gets the full object template :param object_template: template or ID to get @@ -711,14 +711,14 @@ class PyMISP: t.from_dict(**object_template_r) return t - def get_raw_object_template(self, uuid_or_name: str) -> dict: + def get_raw_object_template(self, uuid_or_name: str) -> dict[str, Any]: """Get a row template. It needs to be present on disk on the MISP instance you're connected to. The response of this method can be passed to MISPObject(, misp_objects_template_custom=) """ r = self._prepare_request('GET', f'objectTemplates/getRaw/{uuid_or_name}') return self._check_json_response(r) - def update_object_templates(self) -> dict: + def update_object_templates(self) -> dict[str, Any]: """Trigger an update of the object templates""" response = self._prepare_request('POST', 'objectTemplates/update') return self._check_json_response(response) @@ -727,14 +727,14 @@ class PyMISP: # ## BEGIN Attribute ### - def attributes(self, pythonify: bool = False) -> dict | list[MISPAttribute]: + def attributes(self, pythonify: bool = False) -> dict[str, Any] | list[MISPAttribute] | list[dict[str, Any]]: """Get all the attributes from the MISP instance: https://www.misp-project.org/openapi/#tag/Attributes/operation/getAttributes :param pythonify: Returns a list of PyMISP Objects instead of the plain json output. Warning: it might use a lot of RAM """ r = self._prepare_request('GET', 'attributes/index') - attributes_r = self._check_json_response(r) - if not (self.global_pythonify or pythonify) or 'errors' in attributes_r: + attributes_r = self._check_json_response_list(r) + if not (self.global_pythonify or pythonify) or isinstance(attributes_r, dict): return attributes_r to_return = [] for attribute in attributes_r: @@ -743,7 +743,7 @@ class PyMISP: to_return.append(a) return to_return - def get_attribute(self, attribute: MISPAttribute | int | str | UUID, pythonify: bool = False) -> dict | MISPAttribute: + def get_attribute(self, attribute: MISPAttribute | int | str | UUID, pythonify: bool = False) -> dict[str, Any] | MISPAttribute: """Get an attribute from a MISP instance: https://www.misp-project.org/openapi/#tag/Attributes/operation/getAttributeById :param attribute: attribute to get @@ -767,7 +767,7 @@ class PyMISP: r = self._prepare_request('HEAD', f'attributes/view/{attribute_id}') return self._check_head_response(r) - def add_attribute(self, event: MISPEvent | int | str | UUID, attribute: MISPAttribute | Iterable, pythonify: bool = False, break_on_duplicate: bool = True) -> dict | MISPAttribute | MISPShadowAttribute: + def add_attribute(self, event: MISPEvent | int | str | UUID, attribute: MISPAttribute | Iterable[str], pythonify: bool = False, break_on_duplicate: bool = True) -> dict[str, Any] | MISPAttribute | MISPShadowAttribute: """Add an attribute to an existing MISP event: https://www.misp-project.org/openapi/#tag/Attributes/operation/addAttribute :param event: event to extend @@ -814,7 +814,7 @@ class PyMISP: a.from_dict(**new_attribute) return a - def update_attribute(self, attribute: MISPAttribute, attribute_id: int | None = None, pythonify: bool = False) -> dict | MISPAttribute | MISPShadowAttribute: + def update_attribute(self, attribute: MISPAttribute, attribute_id: int | None = None, pythonify: bool = False) -> dict[str, Any] | MISPAttribute | MISPShadowAttribute: """Update an attribute on a MISP instance: https://www.misp-project.org/openapi/#tag/Attributes/operation/editAttribute :param attribute: attribute to update @@ -839,7 +839,7 @@ class PyMISP: a.from_dict(**updated_attribute) return a - def delete_attribute(self, attribute: MISPAttribute | int | str | UUID, hard: bool = False) -> dict: + def delete_attribute(self, attribute: MISPAttribute | int | str | UUID, hard: bool = False) -> dict[str, Any]: """Delete an attribute from a MISP instance: https://www.misp-project.org/openapi/#tag/Attributes/operation/deleteAttribute :param attribute: attribute to delete @@ -859,7 +859,7 @@ class PyMISP: return self.delete_attribute_proposal(attribute_id) return response - def restore_attribute(self, attribute: MISPAttribute | int | str | UUID, pythonify: bool = False) -> dict | MISPAttribute: + def restore_attribute(self, attribute: MISPAttribute | int | str | UUID, pythonify: bool = False) -> dict[str, Any] | MISPAttribute: """Restore a soft deleted attribute from a MISP instance: https://www.misp-project.org/openapi/#tag/Attributes/operation/restoreAttribute :param attribute: attribute to restore @@ -877,7 +877,7 @@ class PyMISP: # ## BEGIN Attribute Proposal ### - def attribute_proposals(self, event: MISPEvent | int | str | UUID | None = None, pythonify: bool = False) -> dict | list[MISPShadowAttribute]: + def attribute_proposals(self, event: MISPEvent | int | str | UUID | None = None, pythonify: bool = False) -> dict[str, Any] | list[MISPShadowAttribute] | list[dict[str, Any]]: """Get all the attribute proposals :param event: event @@ -888,8 +888,8 @@ class PyMISP: r = self._prepare_request('GET', f'shadowAttributes/index/{event_id}') else: r = self._prepare_request('GET', 'shadowAttributes/index') - attribute_proposals = self._check_json_response(r) - if not (self.global_pythonify or pythonify) or 'errors' in attribute_proposals: + attribute_proposals = self._check_json_response_list(r) + if not (self.global_pythonify or pythonify) or isinstance(attribute_proposals, dict): return attribute_proposals to_return = [] for attribute_proposal in attribute_proposals: @@ -898,7 +898,7 @@ class PyMISP: to_return.append(a) return to_return - def get_attribute_proposal(self, proposal: MISPShadowAttribute | int | str | UUID, pythonify: bool = False) -> dict | MISPShadowAttribute: + def get_attribute_proposal(self, proposal: MISPShadowAttribute | int | str | UUID, pythonify: bool = False) -> dict[str, Any] | MISPShadowAttribute: """Get an attribute proposal :param proposal: proposal to get @@ -915,7 +915,7 @@ class PyMISP: # NOTE: the tree following method have a very specific meaning, look at the comments - def add_attribute_proposal(self, event: MISPEvent | int | str | UUID, attribute: MISPAttribute, pythonify: bool = False) -> dict | MISPShadowAttribute: + def add_attribute_proposal(self, event: MISPEvent | int | str | UUID, attribute: MISPAttribute, pythonify: bool = False) -> dict[str, Any] | MISPShadowAttribute: """Propose a new attribute in an event :param event: event to receive new attribute @@ -931,7 +931,7 @@ class PyMISP: a.from_dict(**new_attribute_proposal) return a - def update_attribute_proposal(self, initial_attribute: MISPAttribute | int | str | UUID, attribute: MISPAttribute, pythonify: bool = False) -> dict | MISPShadowAttribute: + def update_attribute_proposal(self, initial_attribute: MISPAttribute | int | str | UUID, attribute: MISPAttribute, pythonify: bool = False) -> dict[str, Any] | MISPShadowAttribute: """Propose a change for an attribute :param initial_attribute: attribute to change @@ -947,7 +947,7 @@ class PyMISP: a.from_dict(**update_attribute_proposal) return a - def delete_attribute_proposal(self, attribute: MISPAttribute | int | str | UUID) -> dict: + def delete_attribute_proposal(self, attribute: MISPAttribute | int | str | UUID) -> dict[str, Any]: """Propose the deletion of an attribute :param attribute: attribute to delete @@ -956,7 +956,7 @@ class PyMISP: response = self._prepare_request('POST', f'shadowAttributes/delete/{attribute_id}') return self._check_json_response(response) - def accept_attribute_proposal(self, proposal: MISPShadowAttribute | int | str | UUID) -> dict: + def accept_attribute_proposal(self, proposal: MISPShadowAttribute | int | str | UUID) -> dict[str, Any]: """Accept a proposal. You cannot modify an existing proposal, only accept/discard :param proposal: attribute proposal to accept @@ -965,7 +965,7 @@ class PyMISP: response = self._prepare_request('POST', f'shadowAttributes/accept/{proposal_id}') return self._check_json_response(response) - def discard_attribute_proposal(self, proposal: MISPShadowAttribute | int | str | UUID) -> dict: + def discard_attribute_proposal(self, proposal: MISPShadowAttribute | int | str | UUID) -> dict[str, Any]: """Discard a proposal. You cannot modify an existing proposal, only accept/discard :param proposal: attribute proposal to discard @@ -980,7 +980,7 @@ class PyMISP: def sightings(self, misp_entity: AbstractMISP | None = None, org: MISPOrganisation | int | str | UUID | None = None, - pythonify: bool = False) -> dict | list[MISPSighting]: + pythonify: bool = False) -> dict[str, Any] | list[MISPSighting] | list[dict[str, Any]]: """Get the list of sightings related to a MISPEvent or a MISPAttribute (depending on type of misp_entity): https://www.misp-project.org/openapi/#tag/Sightings/operation/getSightingsByEventId :param misp_entity: MISP entity @@ -1002,8 +1002,8 @@ class PyMISP: to_post['org_id'] = org_id r = self._prepare_request('POST', url, data=to_post) - sightings = self._check_json_response(r) - if not (self.global_pythonify or pythonify) or 'errors' in sightings: + sightings = self._check_json_response_list(r) + if not (self.global_pythonify or pythonify) or isinstance(sightings, dict): return sightings to_return = [] for sighting in sightings: @@ -1014,7 +1014,7 @@ class PyMISP: def add_sighting(self, sighting: MISPSighting, attribute: MISPAttribute | int | str | UUID | None = None, - pythonify: bool = False) -> dict | MISPSighting: + pythonify: bool = False) -> dict[str, Any] | MISPSighting: """Add a new sighting (globally, or to a specific attribute): https://www.misp-project.org/openapi/#tag/Sightings/operation/addSighting and https://www.misp-project.org/openapi/#tag/Sightings/operation/getSightingsByEventId :param sighting: sighting to add @@ -1034,7 +1034,7 @@ class PyMISP: s.from_dict(**new_sighting) return s - def delete_sighting(self, sighting: MISPSighting | int | str | UUID) -> dict: + def delete_sighting(self, sighting: MISPSighting | int | str | UUID) -> dict[str, Any]: """Delete a sighting from a MISP instance: https://www.misp-project.org/openapi/#tag/Sightings/operation/deleteSighting :param sighting: sighting to delete @@ -1047,7 +1047,7 @@ class PyMISP: # ## BEGIN Tags ### - def tags(self, pythonify: bool = False, **kw_params) -> dict | list[MISPTag]: + def tags(self, pythonify: bool = False, **kw_params) -> dict[str, Any] | list[MISPTag]: # type: ignore[no-untyped-def] """Get the list of existing tags: https://www.misp-project.org/openapi/#tag/Tags/operation/getTags :param pythonify: Returns a list of PyMISP Objects instead of the plain json output. Warning: it might use a lot of RAM @@ -1063,7 +1063,7 @@ class PyMISP: to_return.append(t) return to_return - def get_tag(self, tag: MISPTag | int | str | UUID, pythonify: bool = False) -> dict | MISPTag: + def get_tag(self, tag: MISPTag | int | str | UUID, pythonify: bool = False) -> dict[str, Any] | MISPTag: """Get a tag by id: https://www.misp-project.org/openapi/#tag/Tags/operation/getTagById :param tag: tag to get @@ -1078,7 +1078,7 @@ class PyMISP: t.from_dict(**tag_r) return t - def add_tag(self, tag: MISPTag, pythonify: bool = False) -> dict | MISPTag: + def add_tag(self, tag: MISPTag, pythonify: bool = False) -> dict[str, Any] | MISPTag: """Add a new tag on a MISP instance: https://www.misp-project.org/openapi/#tag/Tags/operation/addTag The user calling this method needs the Tag Editor permission. It doesn't add a tag to an event, simply creates it on the MISP instance. @@ -1094,7 +1094,7 @@ class PyMISP: t.from_dict(**new_tag) return t - def enable_tag(self, tag: MISPTag, pythonify: bool = False) -> dict | MISPTag: + def enable_tag(self, tag: MISPTag, pythonify: bool = False) -> dict[str, Any] | MISPTag: """Enable a tag :param tag: tag to enable @@ -1103,7 +1103,7 @@ class PyMISP: tag.hide_tag = False return self.update_tag(tag, pythonify=pythonify) - def disable_tag(self, tag: MISPTag, pythonify: bool = False) -> dict | MISPTag: + def disable_tag(self, tag: MISPTag, pythonify: bool = False) -> dict[str, Any] | MISPTag: """Disable a tag :param tag: tag to disable @@ -1112,7 +1112,7 @@ class PyMISP: tag.hide_tag = True return self.update_tag(tag, pythonify=pythonify) - def update_tag(self, tag: MISPTag, tag_id: int | None = None, pythonify: bool = False) -> dict | MISPTag: + def update_tag(self, tag: MISPTag, tag_id: int | None = None, pythonify: bool = False) -> dict[str, Any] | MISPTag: """Edit only the provided parameters of a tag: https://www.misp-project.org/openapi/#tag/Tags/operation/editTag :param tag: tag to update @@ -1131,7 +1131,7 @@ class PyMISP: t.from_dict(**updated_tag) return t - def delete_tag(self, tag: MISPTag | int | str | UUID) -> dict: + def delete_tag(self, tag: MISPTag | int | str | UUID) -> dict[str, Any]: """Delete a tag from a MISP instance: https://www.misp-project.org/openapi/#tag/Tags/operation/deleteTag :param tag: tag to delete @@ -1140,7 +1140,7 @@ class PyMISP: response = self._prepare_request('POST', f'tags/delete/{tag_id}') return self._check_json_response(response) - def search_tags(self, tagname: str, strict_tagname: bool = False, pythonify: bool = False) -> dict | list[MISPTag]: + def search_tags(self, tagname: str, strict_tagname: bool = False, pythonify: bool = False) -> dict[str, Any] | list[MISPTag] | list[dict[str, Any]]: """Search for tags by name: https://www.misp-project.org/openapi/#tag/Tags/operation/searchTag :param tag_name: Name to search, use % for substrings matches. @@ -1148,8 +1148,8 @@ class PyMISP: """ query = {'tagname': tagname, 'strict_tagname': strict_tagname} response = self._prepare_request('POST', 'tags/search', data=query) - normalized_response = self._check_json_response(response) - if not (self.global_pythonify or pythonify) or 'errors' in normalized_response: + normalized_response = self._check_json_response_list(response) + if not (self.global_pythonify or pythonify) or isinstance(normalized_response, dict): return normalized_response to_return: list[MISPTag] = [] for tag in normalized_response: @@ -1162,14 +1162,14 @@ class PyMISP: # ## BEGIN Taxonomies ### - def taxonomies(self, pythonify: bool = False) -> dict | list[MISPTaxonomy]: + def taxonomies(self, pythonify: bool = False) -> dict[str, Any] | list[MISPTaxonomy] | list[dict[str, Any]]: """Get all the taxonomies: https://www.misp-project.org/openapi/#tag/Taxonomies/operation/getTaxonomies :param pythonify: Returns a list of PyMISP Objects instead of the plain json output. Warning: it might use a lot of RAM """ r = self._prepare_request('GET', 'taxonomies/index') - taxonomies = self._check_json_response(r) - if not (self.global_pythonify or pythonify) or 'errors' in taxonomies: + taxonomies = self._check_json_response_list(r) + if not (self.global_pythonify or pythonify) or isinstance(taxonomies, dict): return taxonomies to_return = [] for taxonomy in taxonomies: @@ -1178,7 +1178,7 @@ class PyMISP: to_return.append(t) return to_return - def get_taxonomy(self, taxonomy: MISPTaxonomy | int | str | UUID, pythonify: bool = False) -> dict | MISPTaxonomy: + def get_taxonomy(self, taxonomy: MISPTaxonomy | int | str | UUID, pythonify: bool = False) -> dict[str, Any] | MISPTaxonomy: """Get a taxonomy by id or namespace from a MISP instance: https://www.misp-project.org/openapi/#tag/Taxonomies/operation/getTaxonomyById :param taxonomy: taxonomy to get @@ -1193,7 +1193,7 @@ class PyMISP: t.from_dict(**taxonomy_r) return t - def enable_taxonomy(self, taxonomy: MISPTaxonomy | int | str | UUID) -> dict: + def enable_taxonomy(self, taxonomy: MISPTaxonomy | int | str | UUID) -> dict[str, Any]: """Enable a taxonomy: https://www.misp-project.org/openapi/#tag/Taxonomies/operation/enableTaxonomy :param taxonomy: taxonomy to enable @@ -1202,7 +1202,7 @@ class PyMISP: response = self._prepare_request('POST', f'taxonomies/enable/{taxonomy_id}') return self._check_json_response(response) - def disable_taxonomy(self, taxonomy: MISPTaxonomy | int | str | UUID) -> dict: + def disable_taxonomy(self, taxonomy: MISPTaxonomy | int | str | UUID) -> dict[str, Any]: """Disable a taxonomy: https://www.misp-project.org/openapi/#tag/Taxonomies/operation/disableTaxonomy :param taxonomy: taxonomy to disable @@ -1212,7 +1212,7 @@ class PyMISP: response = self._prepare_request('POST', f'taxonomies/disable/{taxonomy_id}') return self._check_json_response(response) - def disable_taxonomy_tags(self, taxonomy: MISPTaxonomy | int | str | UUID) -> dict: + def disable_taxonomy_tags(self, taxonomy: MISPTaxonomy | int | str | UUID) -> dict[str, Any]: """Disable all the tags of a taxonomy :param taxonomy: taxonomy with tags to disable @@ -1221,7 +1221,7 @@ class PyMISP: response = self._prepare_request('POST', f'taxonomies/disableTag/{taxonomy_id}') return self._check_json_response(response) - def enable_taxonomy_tags(self, taxonomy: MISPTaxonomy | int | str | UUID) -> dict: + def enable_taxonomy_tags(self, taxonomy: MISPTaxonomy | int | str | UUID) -> dict[str, Any]: """Enable all the tags of a taxonomy. NOTE: this is automatically done when you call enable_taxonomy :param taxonomy: taxonomy with tags to enable @@ -1238,12 +1238,12 @@ class PyMISP: response = self._prepare_request('POST', url) return self._check_json_response(response) - def update_taxonomies(self) -> dict: + def update_taxonomies(self) -> dict[str, Any]: """Update all the taxonomies: https://www.misp-project.org/openapi/#tag/Taxonomies/operation/updateTaxonomies""" response = self._prepare_request('POST', 'taxonomies/update') return self._check_json_response(response) - def set_taxonomy_required(self, taxonomy: MISPTaxonomy | int | str, required: bool = False) -> dict: + def set_taxonomy_required(self, taxonomy: MISPTaxonomy | int | str, required: bool = False) -> dict[str, Any]: taxonomy_id = get_uuid_or_id_from_abstract_misp(taxonomy) url = urljoin(self.root_url, f'taxonomies/toggleRequired/{taxonomy_id}') payload = { @@ -1258,7 +1258,7 @@ class PyMISP: # ## BEGIN Warninglists ### - def warninglists(self, pythonify: bool = False) -> dict | list[MISPWarninglist]: + def warninglists(self, pythonify: bool = False) -> dict[str, Any] | list[MISPWarninglist]: """Get all the warninglists: https://www.misp-project.org/openapi/#tag/Warninglists/operation/getWarninglists :param pythonify: Returns a list of PyMISP Objects instead of the plain json output. Warning: it might use a lot of RAM @@ -1274,7 +1274,7 @@ class PyMISP: to_return.append(w) return to_return - def get_warninglist(self, warninglist: MISPWarninglist | int | str | UUID, pythonify: bool = False) -> dict | MISPWarninglist: + def get_warninglist(self, warninglist: MISPWarninglist | int | str | UUID, pythonify: bool = False) -> dict[str, Any] | MISPWarninglist: """Get a warninglist by id: https://www.misp-project.org/openapi/#tag/Warninglists/operation/getWarninglistById :param warninglist: warninglist to get @@ -1289,7 +1289,7 @@ class PyMISP: w.from_dict(**wl) return w - def toggle_warninglist(self, warninglist_id: str | int | list[int] | None = None, warninglist_name: str | list[str] | None = None, force_enable: bool = False) -> dict: + def toggle_warninglist(self, warninglist_id: str | int | list[int] | None = None, warninglist_name: str | list[str] | None = None, force_enable: bool = False) -> dict[str, Any]: '''Toggle (enable/disable) the status of a warninglist by id: https://www.misp-project.org/openapi/#tag/Warninglists/operation/toggleEnableWarninglist :param warninglist_id: ID of the WarningList @@ -1314,7 +1314,7 @@ class PyMISP: response = self._prepare_request('POST', 'warninglists/toggleEnable', data=query) return self._check_json_response(response) - def enable_warninglist(self, warninglist: MISPWarninglist | int | str | UUID) -> dict: + def enable_warninglist(self, warninglist: MISPWarninglist | int | str | UUID) -> dict[str, Any]: """Enable a warninglist :param warninglist: warninglist to enable @@ -1322,7 +1322,7 @@ class PyMISP: warninglist_id = get_uuid_or_id_from_abstract_misp(warninglist) return self.toggle_warninglist(warninglist_id=warninglist_id, force_enable=True) - def disable_warninglist(self, warninglist: MISPWarninglist | int | str | UUID) -> dict: + def disable_warninglist(self, warninglist: MISPWarninglist | int | str | UUID) -> dict[str, Any]: """Disable a warninglist :param warninglist: warninglist to disable @@ -1330,7 +1330,7 @@ class PyMISP: warninglist_id = get_uuid_or_id_from_abstract_misp(warninglist) return self.toggle_warninglist(warninglist_id=warninglist_id, force_enable=False) - def values_in_warninglist(self, value: Iterable) -> dict: + def values_in_warninglist(self, value: Iterable[str]) -> dict[str, Any]: """Check if IOC values are in warninglist :param value: iterator with values to check @@ -1338,7 +1338,7 @@ class PyMISP: response = self._prepare_request('POST', 'warninglists/checkValue', data=value) return self._check_json_response(response) - def update_warninglists(self) -> dict: + def update_warninglists(self) -> dict[str, Any]: """Update all the warninglists: https://www.misp-project.org/openapi/#tag/Warninglists/operation/updateWarninglists""" response = self._prepare_request('POST', 'warninglists/update') return self._check_json_response(response) @@ -1347,14 +1347,14 @@ class PyMISP: # ## BEGIN Noticelist ### - def noticelists(self, pythonify: bool = False) -> dict | list[MISPNoticelist]: + def noticelists(self, pythonify: bool = False) -> dict[str, Any] | list[MISPNoticelist] | list[dict[str, Any]]: """Get all the noticelists: https://www.misp-project.org/openapi/#tag/Noticelists/operation/getNoticelists :param pythonify: Returns a list of PyMISP Objects instead of the plain json output. Warning: it might use a lot of RAM """ r = self._prepare_request('GET', 'noticelists/index') - noticelists = self._check_json_response(r) - if not (self.global_pythonify or pythonify) or 'errors' in noticelists: + noticelists = self._check_json_response_list(r) + if not (self.global_pythonify or pythonify) or isinstance(noticelists, dict): return noticelists to_return = [] for noticelist in noticelists: @@ -1363,7 +1363,7 @@ class PyMISP: to_return.append(n) return to_return - def get_noticelist(self, noticelist: MISPNoticelist | int | str | UUID, pythonify: bool = False) -> dict | MISPNoticelist: + def get_noticelist(self, noticelist: MISPNoticelist | int | str | UUID, pythonify: bool = False) -> dict[str, Any] | MISPNoticelist: """Get a noticelist by id: https://www.misp-project.org/openapi/#tag/Noticelists/operation/getNoticelistById :param notistlist: Noticelist to get @@ -1378,7 +1378,7 @@ class PyMISP: n.from_dict(**noticelist_j) return n - def enable_noticelist(self, noticelist: MISPNoticelist | int | str | UUID) -> dict: + def enable_noticelist(self, noticelist: MISPNoticelist | int | str | UUID) -> dict[str, Any]: """Enable a noticelist by id: https://www.misp-project.org/openapi/#tag/Noticelists/operation/toggleEnableNoticelist :param noticelist: Noticelist to enable @@ -1389,7 +1389,7 @@ class PyMISP: response = self._prepare_request('POST', f'noticelists/enableNoticelist/{noticelist_id}/true') return self._check_json_response(response) - def disable_noticelist(self, noticelist: MISPNoticelist | int | str | UUID) -> dict: + def disable_noticelist(self, noticelist: MISPNoticelist | int | str | UUID) -> dict[str, Any]: """Disable a noticelist by id :param noticelist: Noticelist to disable @@ -1400,7 +1400,7 @@ class PyMISP: response = self._prepare_request('POST', f'noticelists/enableNoticelist/{noticelist_id}') return self._check_json_response(response) - def update_noticelists(self) -> dict: + def update_noticelists(self) -> dict[str, Any]: """Update all the noticelists: https://www.misp-project.org/openapi/#tag/Noticelists/operation/updateNoticelists""" response = self._prepare_request('POST', 'noticelists/update') return self._check_json_response(response) @@ -1409,14 +1409,14 @@ class PyMISP: # ## BEGIN Correlation Exclusions ### - def correlation_exclusions(self, pythonify: bool = False) -> dict | list[MISPCorrelationExclusion]: + def correlation_exclusions(self, pythonify: bool = False) -> dict[str, Any] | list[MISPCorrelationExclusion] | list[dict[str, Any]]: """Get all the correlation exclusions :param pythonify: Returns a list of PyMISP Objects instead of the plain json output. Warning: it might use a lot of RAM """ r = self._prepare_request('GET', 'correlation_exclusions') - correlation_exclusions = self._check_json_response(r) - if not (self.global_pythonify or pythonify) or 'errors' in correlation_exclusions: + correlation_exclusions = self._check_json_response_list(r) + if not (self.global_pythonify or pythonify) or isinstance(correlation_exclusions, dict): return correlation_exclusions to_return = [] for correlation_exclusion in correlation_exclusions: @@ -1425,7 +1425,7 @@ class PyMISP: to_return.append(c) return to_return - def get_correlation_exclusion(self, correlation_exclusion: MISPCorrelationExclusion | int | str | UUID, pythonify: bool = False) -> dict | MISPCorrelationExclusion: + def get_correlation_exclusion(self, correlation_exclusion: MISPCorrelationExclusion | int | str | UUID, pythonify: bool = False) -> dict[str, Any] | MISPCorrelationExclusion: """Get a correlation exclusion by ID :param correlation_exclusion: Correlation exclusion to get @@ -1440,7 +1440,7 @@ class PyMISP: c.from_dict(**correlation_exclusion_j) return c - def add_correlation_exclusion(self, correlation_exclusion: MISPCorrelationExclusion, pythonify: bool = False) -> dict | MISPCorrelationExclusion: + def add_correlation_exclusion(self, correlation_exclusion: MISPCorrelationExclusion, pythonify: bool = False) -> dict[str, Any] | MISPCorrelationExclusion: """Add a new correlation exclusion :param correlation_exclusion: correlation exclusion to add @@ -1454,7 +1454,7 @@ class PyMISP: c.from_dict(**new_correlation_exclusion) return c - def delete_correlation_exclusion(self, correlation_exclusion: MISPCorrelationExclusion | int | str | UUID) -> dict: + def delete_correlation_exclusion(self, correlation_exclusion: MISPCorrelationExclusion | int | str | UUID) -> dict[str, Any]: """Delete a correlation exclusion :param correlation_exclusion: The MISPCorrelationExclusion you wish to delete from MISP @@ -1463,7 +1463,7 @@ class PyMISP: r = self._prepare_request('POST', f'correlation_exclusions/delete/{exclusion_id}') return self._check_json_response(r) - def clean_correlation_exclusions(self): + def clean_correlation_exclusions(self) -> dict[str, Any]: """Initiate correlation exclusions cleanup""" r = self._prepare_request('POST', 'correlation_exclusions/clean') return self._check_json_response(r) @@ -1476,14 +1476,14 @@ class PyMISP: self, withCluster: bool = False, pythonify: bool = False, - ) -> dict | list[MISPGalaxy]: + ) -> dict[str, Any] | list[MISPGalaxy] | list[dict[str, Any]]: """Get all the galaxies: https://www.misp-project.org/openapi/#tag/Galaxies/operation/getGalaxies :param pythonify: Returns a list of PyMISP Objects instead of the plain json output. Warning: it might use a lot of RAM """ r = self._prepare_request('GET', 'galaxies/index') - galaxies = self._check_json_response(r) - if not (self.global_pythonify or pythonify) or 'errors' in galaxies: + galaxies = self._check_json_response_list(r) + if not (self.global_pythonify or pythonify) or isinstance(galaxies, dict): return galaxies to_return = [] for galaxy in galaxies: @@ -1497,11 +1497,11 @@ class PyMISP: value: str, withCluster: bool = False, pythonify: bool = False, - ) -> dict | list[MISPGalaxy]: + ) -> dict[str, Any] | list[MISPGalaxy] | list[dict[str, Any]]: """Text search to find a matching galaxy name, namespace, description, or uuid.""" r = self._prepare_request("POST", "galaxies", data={"value": value}) - galaxies = self._check_json_response(r) - if not (self.global_pythonify or pythonify) or "errors" in galaxies: + galaxies = self._check_json_response_list(r) + if not (self.global_pythonify or pythonify) or isinstance(galaxies, dict): return galaxies to_return = [] for galaxy in galaxies: @@ -1510,7 +1510,7 @@ class PyMISP: to_return.append(g) return to_return - def get_galaxy(self, galaxy: MISPGalaxy | int | str | UUID, withCluster: bool = False, pythonify: bool = False) -> dict | MISPGalaxy: + def get_galaxy(self, galaxy: MISPGalaxy | int | str | UUID, withCluster: bool = False, pythonify: bool = False) -> dict[str, Any] | MISPGalaxy: """Get a galaxy by id: https://www.misp-project.org/openapi/#tag/Galaxies/operation/getGalaxyById :param galaxy: galaxy to get @@ -1526,7 +1526,7 @@ class PyMISP: g.from_dict(**galaxy_j, withCluster=withCluster) return g - def search_galaxy_clusters(self, galaxy: MISPGalaxy | int | str | UUID, context: str = "all", searchall: str | None = None, pythonify: bool = False) -> dict | list[MISPGalaxyCluster]: + def search_galaxy_clusters(self, galaxy: MISPGalaxy | int | str | UUID, context: str = "all", searchall: str | None = None, pythonify: bool = False) -> dict[str, Any] | list[MISPGalaxyCluster] | list[dict[str, Any]]: """Searches the galaxy clusters within a specific galaxy: https://www.misp-project.org/openapi/#tag/Galaxy-Clusters/operation/getGalaxyClusters and https://www.misp-project.org/openapi/#tag/Galaxy-Clusters/operation/getGalaxyClusterById :param galaxy: The MISPGalaxy you wish to search in @@ -1543,8 +1543,8 @@ class PyMISP: if searchall: kw_params["searchall"] = searchall r = self._prepare_request('POST', f"galaxy_clusters/index/{galaxy_id}", data=kw_params) - clusters_j = self._check_json_response(r) - if not (self.global_pythonify or pythonify) or 'errors' in clusters_j: + clusters_j = self._check_json_response_list(r) + if not (self.global_pythonify or pythonify) or isinstance(clusters_j, dict): return clusters_j response = [] for cluster in clusters_j: @@ -1553,12 +1553,12 @@ class PyMISP: response.append(c) return response - def update_galaxies(self) -> dict: + def update_galaxies(self) -> dict[str, Any]: """Update all the galaxies: https://www.misp-project.org/openapi/#tag/Galaxies/operation/updateGalaxies""" response = self._prepare_request('POST', 'galaxies/update') return self._check_json_response(response) - def get_galaxy_cluster(self, galaxy_cluster: MISPGalaxyCluster | int | str | UUID, pythonify: bool = False) -> dict | MISPGalaxyCluster: + def get_galaxy_cluster(self, galaxy_cluster: MISPGalaxyCluster | int | str | UUID, pythonify: bool = False) -> dict[str, Any] | MISPGalaxyCluster: """Gets a specific galaxy cluster :param galaxy_cluster: The MISPGalaxyCluster you want to get @@ -1574,7 +1574,7 @@ class PyMISP: gc.from_dict(**cluster_j) return gc - def add_galaxy_cluster(self, galaxy: MISPGalaxy | str | UUID, galaxy_cluster: MISPGalaxyCluster, pythonify: bool = False) -> dict | MISPGalaxyCluster: + def add_galaxy_cluster(self, galaxy: MISPGalaxy | str | UUID, galaxy_cluster: MISPGalaxyCluster, pythonify: bool = False) -> dict[str, Any] | MISPGalaxyCluster: """Add a new galaxy cluster to a MISP Galaxy: https://www.misp-project.org/openapi/#tag/Galaxy-Clusters/operation/addGalaxyCluster :param galaxy: A MISPGalaxy (or UUID) where you wish to add the galaxy cluster @@ -1594,7 +1594,7 @@ class PyMISP: gc.from_dict(**cluster_j) return gc - def update_galaxy_cluster(self, galaxy_cluster: MISPGalaxyCluster, pythonify: bool = False) -> dict | MISPGalaxyCluster: + def update_galaxy_cluster(self, galaxy_cluster: MISPGalaxyCluster, pythonify: bool = False) -> dict[str, Any] | MISPGalaxyCluster: """Update a custom galaxy cluster: https://www.misp-project.org/openapi/#tag/Galaxy-Clusters/operation/editGalaxyCluster ;param galaxy_cluster: The MISPGalaxyCluster you wish to update @@ -1613,7 +1613,7 @@ class PyMISP: gc.from_dict(**cluster_j) return gc - def publish_galaxy_cluster(self, galaxy_cluster: MISPGalaxyCluster | int | str | UUID) -> dict: + def publish_galaxy_cluster(self, galaxy_cluster: MISPGalaxyCluster | int | str | UUID) -> dict[str, Any]: """Publishes a galaxy cluster: https://www.misp-project.org/openapi/#tag/Galaxy-Clusters/operation/publishGalaxyCluster :param galaxy_cluster: The galaxy cluster you wish to publish @@ -1625,7 +1625,7 @@ class PyMISP: response = self._check_json_response(r) return response - def fork_galaxy_cluster(self, galaxy: MISPGalaxy | int | str | UUID, galaxy_cluster: MISPGalaxyCluster, pythonify: bool = False) -> dict | MISPGalaxyCluster: + def fork_galaxy_cluster(self, galaxy: MISPGalaxy | int | str | UUID, galaxy_cluster: MISPGalaxyCluster, pythonify: bool = False) -> dict[str, Any] | MISPGalaxyCluster: """Forks an existing galaxy cluster, creating a new one with matching attributes :param galaxy: The galaxy (or galaxy ID) where the cluster you want to fork resides @@ -1649,7 +1649,7 @@ class PyMISP: gc.from_dict(**cluster_j) return gc - def delete_galaxy_cluster(self, galaxy_cluster: MISPGalaxyCluster | int | str | UUID, hard=False) -> dict: + def delete_galaxy_cluster(self, galaxy_cluster: MISPGalaxyCluster | int | str | UUID, hard: bool=False) -> dict[str, Any]: """Deletes a galaxy cluster from MISP: https://www.misp-project.org/openapi/#tag/Galaxy-Clusters/operation/deleteGalaxyCluster :param galaxy_cluster: The MISPGalaxyCluster you wish to delete from MISP @@ -1665,7 +1665,7 @@ class PyMISP: r = self._prepare_request('POST', f'galaxy_clusters/delete/{cluster_id}', data=data) return self._check_json_response(r) - def add_galaxy_cluster_relation(self, galaxy_cluster_relation: MISPGalaxyClusterRelation) -> dict: + def add_galaxy_cluster_relation(self, galaxy_cluster_relation: MISPGalaxyClusterRelation) -> dict[str, Any]: """Add a galaxy cluster relation, cluster relation must include cluster UUIDs in both directions @@ -1675,7 +1675,7 @@ class PyMISP: cluster_rel_j = self._check_json_response(r) return cluster_rel_j - def update_galaxy_cluster_relation(self, galaxy_cluster_relation: MISPGalaxyClusterRelation) -> dict: + def update_galaxy_cluster_relation(self, galaxy_cluster_relation: MISPGalaxyClusterRelation) -> dict[str, Any]: """Update a galaxy cluster relation :param galaxy_cluster_relation: The MISPGalaxyClusterRelation to update @@ -1685,7 +1685,7 @@ class PyMISP: cluster_rel_j = self._check_json_response(r) return cluster_rel_j - def delete_galaxy_cluster_relation(self, galaxy_cluster_relation: MISPGalaxyClusterRelation | int | str | UUID) -> dict: + def delete_galaxy_cluster_relation(self, galaxy_cluster_relation: MISPGalaxyClusterRelation | int | str | UUID) -> dict[str, Any]: """Delete a galaxy cluster relation :param galaxy_cluster_relation: The MISPGalaxyClusterRelation to delete @@ -1699,14 +1699,14 @@ class PyMISP: # ## BEGIN Feed ### - def feeds(self, pythonify: bool = False) -> dict | list[MISPFeed]: + def feeds(self, pythonify: bool = False) -> dict[str, Any] | list[MISPFeed] | list[dict[str, Any]]: """Get the list of existing feeds: https://www.misp-project.org/openapi/#tag/Feeds/operation/getFeeds :param pythonify: Returns a list of PyMISP Objects instead of the plain json output. Warning: it might use a lot of RAM """ r = self._prepare_request('GET', 'feeds/index') - feeds = self._check_json_response(r) - if not (self.global_pythonify or pythonify) or 'errors' in feeds: + feeds = self._check_json_response_list(r) + if not (self.global_pythonify or pythonify) or isinstance(feeds, dict): return feeds to_return = [] for feed in feeds: @@ -1715,7 +1715,7 @@ class PyMISP: to_return.append(f) return to_return - def get_feed(self, feed: MISPFeed | int | str | UUID, pythonify: bool = False) -> dict | MISPFeed: + def get_feed(self, feed: MISPFeed | int | str | UUID, pythonify: bool = False) -> dict[str, Any] | MISPFeed: """Get a feed by id: https://www.misp-project.org/openapi/#tag/Feeds/operation/getFeedById :param feed: feed to get @@ -1730,7 +1730,7 @@ class PyMISP: f.from_dict(**feed_j) return f - def add_feed(self, feed: MISPFeed, pythonify: bool = False) -> dict | MISPFeed: + def add_feed(self, feed: MISPFeed, pythonify: bool = False) -> dict[str, Any] | MISPFeed: """Add a new feed on a MISP instance: https://www.misp-project.org/openapi/#tag/Feeds/operation/addFeed :param feed: feed to add @@ -1745,7 +1745,7 @@ class PyMISP: f.from_dict(**new_feed) return f - def enable_feed(self, feed: MISPFeed | int | str | UUID, pythonify: bool = False) -> dict | MISPFeed: + def enable_feed(self, feed: MISPFeed | int | str | UUID, pythonify: bool = False) -> dict[str, Any] | MISPFeed: """Enable a feed; fetching it will create event(s): https://www.misp-project.org/openapi/#tag/Feeds/operation/enableFeed :param feed: feed to enable @@ -1760,7 +1760,7 @@ class PyMISP: f.enabled = True return self.update_feed(feed=f, pythonify=pythonify) - def disable_feed(self, feed: MISPFeed | int | str | UUID, pythonify: bool = False) -> dict | MISPFeed: + def disable_feed(self, feed: MISPFeed | int | str | UUID, pythonify: bool = False) -> dict[str, Any] | MISPFeed: """Disable a feed: https://www.misp-project.org/openapi/#tag/Feeds/operation/disableFeed :param feed: feed to disable @@ -1775,7 +1775,7 @@ class PyMISP: f.enabled = False return self.update_feed(feed=f, pythonify=pythonify) - def enable_feed_cache(self, feed: MISPFeed | int | str | UUID, pythonify: bool = False) -> dict | MISPFeed: + def enable_feed_cache(self, feed: MISPFeed | int | str | UUID, pythonify: bool = False) -> dict[str, Any] | MISPFeed: """Enable the caching of a feed :param feed: feed to enable caching @@ -1790,7 +1790,7 @@ class PyMISP: f.caching_enabled = True return self.update_feed(feed=f, pythonify=pythonify) - def disable_feed_cache(self, feed: MISPFeed | int | str | UUID, pythonify: bool = False) -> dict | MISPFeed: + def disable_feed_cache(self, feed: MISPFeed | int | str | UUID, pythonify: bool = False) -> dict[str, Any] | MISPFeed: """Disable the caching of a feed :param feed: feed to disable caching @@ -1805,7 +1805,7 @@ class PyMISP: f.caching_enabled = False return self.update_feed(feed=f, pythonify=pythonify) - def update_feed(self, feed: MISPFeed, feed_id: int | None = None, pythonify: bool = False) -> dict | MISPFeed: + def update_feed(self, feed: MISPFeed, feed_id: int | None = None, pythonify: bool = False) -> dict[str, Any] | MISPFeed: """Update a feed on a MISP instance :param feed: feed to update @@ -1825,7 +1825,7 @@ class PyMISP: f.from_dict(**updated_feed) return f - def delete_feed(self, feed: MISPFeed | int | str | UUID) -> dict: + def delete_feed(self, feed: MISPFeed | int | str | UUID) -> dict[str, Any]: """Delete a feed from a MISP instance :param feed: feed to delete @@ -1834,7 +1834,7 @@ class PyMISP: response = self._prepare_request('POST', f'feeds/delete/{feed_id}') return self._check_json_response(response) - def fetch_feed(self, feed: MISPFeed | int | str | UUID) -> dict: + def fetch_feed(self, feed: MISPFeed | int | str | UUID) -> dict[str, Any]: """Fetch one single feed by id: https://www.misp-project.org/openapi/#tag/Feeds/operation/fetchFromFeed :param feed: feed to fetch @@ -1843,12 +1843,12 @@ class PyMISP: response = self._prepare_request('GET', f'feeds/fetchFromFeed/{feed_id}') return self._check_json_response(response) - def cache_all_feeds(self) -> dict: + def cache_all_feeds(self) -> dict[str, Any]: """ Cache all the feeds: https://www.misp-project.org/openapi/#tag/Feeds/operation/cacheFeeds""" response = self._prepare_request('GET', 'feeds/cacheFeeds/all') return self._check_json_response(response) - def cache_feed(self, feed: MISPFeed | int | str | UUID) -> dict: + def cache_feed(self, feed: MISPFeed | int | str | UUID) -> dict[str, Any]: """Cache a specific feed by id: https://www.misp-project.org/openapi/#tag/Feeds/operation/cacheFeeds :param feed: feed to cache @@ -1857,22 +1857,22 @@ class PyMISP: response = self._prepare_request('GET', f'feeds/cacheFeeds/{feed_id}') return self._check_json_response(response) - def cache_freetext_feeds(self) -> dict: + def cache_freetext_feeds(self) -> dict[str, Any]: """Cache all the freetext feeds""" response = self._prepare_request('GET', 'feeds/cacheFeeds/freetext') return self._check_json_response(response) - def cache_misp_feeds(self) -> dict: + def cache_misp_feeds(self) -> dict[str, Any]: """Cache all the MISP feeds""" response = self._prepare_request('GET', 'feeds/cacheFeeds/misp') return self._check_json_response(response) - def compare_feeds(self) -> dict: + def compare_feeds(self) -> dict[str, Any]: """Generate the comparison matrix for all the MISP feeds""" response = self._prepare_request('GET', 'feeds/compareFeeds') return self._check_json_response(response) - def load_default_feeds(self) -> dict: + def load_default_feeds(self) -> dict[str, Any]: """Load all the default feeds.""" response = self._prepare_request('POST', 'feeds/loadDefaultFeeds') return self._check_json_response(response) @@ -1881,14 +1881,14 @@ class PyMISP: # ## BEGIN Server ### - def servers(self, pythonify: bool = False) -> dict | list[MISPServer]: + def servers(self, pythonify: bool = False) -> dict[str, Any] | list[MISPServer] | list[dict[str, Any]]: """Get the existing servers the MISP instance can synchronise with: https://www.misp-project.org/openapi/#tag/Servers/operation/getServers :param pythonify: Returns a list of PyMISP Objects instead of the plain json output. Warning: it might use a lot of RAM """ r = self._prepare_request('GET', 'servers/index') - servers = self._check_json_response(r) - if not (self.global_pythonify or pythonify) or 'errors' in servers: + servers = self._check_json_response_list(r) + if not (self.global_pythonify or pythonify) or isinstance(servers, dict): return servers to_return = [] for server in servers: @@ -1897,7 +1897,7 @@ class PyMISP: to_return.append(s) return to_return - def get_sync_config(self, pythonify: bool = False) -> dict | MISPServer: + def get_sync_config(self, pythonify: bool = False) -> dict[str, Any] | MISPServer: """Get the sync server config. WARNING: This method only works if the user calling it is a sync user @@ -1911,7 +1911,7 @@ class PyMISP: s.from_dict(**server) return s - def import_server(self, server: MISPServer, pythonify: bool = False) -> dict | MISPServer: + def import_server(self, server: MISPServer, pythonify: bool = False) -> dict[str, Any] | MISPServer: """Import a sync server config received from get_sync_config :param server: sync server config @@ -1925,7 +1925,7 @@ class PyMISP: s.from_dict(**server_j) return s - def add_server(self, server: MISPServer, pythonify: bool = False) -> dict | MISPServer: + def add_server(self, server: MISPServer, pythonify: bool = False) -> dict[str, Any] | MISPServer: """Add a server to synchronise with: https://www.misp-project.org/openapi/#tag/Servers/operation/getServers Note: You probably want to use PyMISP.get_sync_config and PyMISP.import_server instead @@ -1940,7 +1940,7 @@ class PyMISP: s.from_dict(**server_j) return s - def update_server(self, server: MISPServer, server_id: int | None = None, pythonify: bool = False) -> dict | MISPServer: + def update_server(self, server: MISPServer, server_id: int | None = None, pythonify: bool = False) -> dict[str, Any] | MISPServer: """Update a server to synchronise with: https://www.misp-project.org/openapi/#tag/Servers/operation/getServers :param server: sync server config @@ -1958,7 +1958,7 @@ class PyMISP: s.from_dict(**updated_server) return s - def delete_server(self, server: MISPServer | int | str | UUID) -> dict: + def delete_server(self, server: MISPServer | int | str | UUID) -> dict[str, Any]: """Delete a sync server: https://www.misp-project.org/openapi/#tag/Servers/operation/getServers :param server: sync server config @@ -1967,7 +1967,7 @@ class PyMISP: response = self._prepare_request('POST', f'servers/delete/{server_id}') return self._check_json_response(response) - def server_pull(self, server: MISPServer | int | str | UUID, event: MISPEvent | int | str | UUID | None = None) -> dict: + def server_pull(self, server: MISPServer | int | str | UUID, event: MISPEvent | int | str | UUID | None = None) -> dict[str, Any]: """Initialize a pull from a sync server, optionally limited to one event: https://www.misp-project.org/openapi/#tag/Servers/operation/pullServer :param server: sync server config @@ -1983,7 +1983,7 @@ class PyMISP: # FIXME: can we pythonify? return self._check_json_response(response) - def server_push(self, server: MISPServer | int | str | UUID, event: MISPEvent | int | str | UUID | None = None) -> dict: + def server_push(self, server: MISPServer | int | str | UUID, event: MISPEvent | int | str | UUID | None = None) -> dict[str, Any]: """Initialize a push to a sync server, optionally limited to one event: https://www.misp-project.org/openapi/#tag/Servers/operation/pushServer :param server: sync server config @@ -1999,7 +1999,7 @@ class PyMISP: # FIXME: can we pythonify? return self._check_json_response(response) - def test_server(self, server: MISPServer | int | str | UUID) -> dict: + def test_server(self, server: MISPServer | int | str | UUID) -> dict[str, Any]: """Test if a sync link is working as expected :param server: sync server config @@ -2012,14 +2012,14 @@ class PyMISP: # ## BEGIN Sharing group ### - def sharing_groups(self, pythonify: bool = False) -> dict | list[MISPSharingGroup]: + def sharing_groups(self, pythonify: bool = False) -> dict[str, Any] | list[MISPSharingGroup] | list[dict[str, Any]]: """Get the existing sharing groups: https://www.misp-project.org/openapi/#tag/Sharing-Groups/operation/getSharingGroup :param pythonify: Returns a list of PyMISP Objects instead of the plain json output. Warning: it might use a lot of RAM """ r = self._prepare_request('GET', 'sharingGroups/index') - sharing_groups = self._check_json_response(r) - if not (self.global_pythonify or pythonify) or 'errors' in sharing_groups: + sharing_groups = self._check_json_response_list(r) + if not (self.global_pythonify or pythonify) or isinstance(sharing_groups, dict): return sharing_groups to_return = [] for sharing_group in sharing_groups: @@ -2028,7 +2028,7 @@ class PyMISP: to_return.append(s) return to_return - def get_sharing_group(self, sharing_group: MISPSharingGroup | int | str | UUID, pythonify: bool = False) -> dict | MISPSharingGroup: + def get_sharing_group(self, sharing_group: MISPSharingGroup | int | str | UUID, pythonify: bool = False) -> dict[str, Any] | MISPSharingGroup: """Get a sharing group: https://www.misp-project.org/openapi/#tag/Sharing-Groups/operation/getSharingGroupById :param sharing_group: sharing group to find @@ -2043,7 +2043,7 @@ class PyMISP: s.from_dict(**sharing_group_resp) return s - def add_sharing_group(self, sharing_group: MISPSharingGroup, pythonify: bool = False) -> dict | MISPSharingGroup: + def add_sharing_group(self, sharing_group: MISPSharingGroup, pythonify: bool = False) -> dict[str, Any] | MISPSharingGroup: """Add a new sharing group: https://www.misp-project.org/openapi/#tag/Sharing-Groups/operation/addSharingGroup :param sharing_group: sharing group to add @@ -2057,7 +2057,7 @@ class PyMISP: s.from_dict(**sharing_group_j) return s - def update_sharing_group(self, sharing_group: MISPSharingGroup | dict, sharing_group_id: int | None = None, pythonify: bool = False) -> dict | MISPSharingGroup: + def update_sharing_group(self, sharing_group: MISPSharingGroup | dict[str, Any], sharing_group_id: int | None = None, pythonify: bool = False) -> dict[str, Any] | MISPSharingGroup: """Update sharing group parameters: https://www.misp-project.org/openapi/#tag/Sharing-Groups/operation/editSharingGroup :param sharing_group: MISP Sharing Group @@ -2086,7 +2086,7 @@ class PyMISP: r = self._prepare_request('HEAD', f'sharing_groups/view/{sharing_group_id}') return self._check_head_response(r) - def delete_sharing_group(self, sharing_group: MISPSharingGroup | int | str | UUID) -> dict: + def delete_sharing_group(self, sharing_group: MISPSharingGroup | int | str | UUID) -> dict[str, Any]: """Delete a sharing group: https://www.misp-project.org/openapi/#tag/Sharing-Groups/operation/deleteSharingGroup :param sharing_group: sharing group to delete @@ -2096,7 +2096,7 @@ class PyMISP: return self._check_json_response(response) def add_org_to_sharing_group(self, sharing_group: MISPSharingGroup | int | str | UUID, - organisation: MISPOrganisation | int | str | UUID, extend: bool = False) -> dict: + organisation: MISPOrganisation | int | str | UUID, extend: bool = False) -> dict[str, Any]: '''Add an organisation to a sharing group: https://www.misp-project.org/openapi/#tag/Sharing-Groups/operation/addOrganisationToSharingGroup :param sharing_group: Sharing group's local instance ID, or Sharing group's global UUID @@ -2110,7 +2110,7 @@ class PyMISP: return self._check_json_response(response) def remove_org_from_sharing_group(self, sharing_group: MISPSharingGroup | int | str | UUID, - organisation: MISPOrganisation | int | str | UUID) -> dict: + organisation: MISPOrganisation | int | str | UUID) -> dict[str, Any]: '''Remove an organisation from a sharing group: https://www.misp-project.org/openapi/#tag/Sharing-Groups/operation/removeOrganisationFromSharingGroup :param sharing_group: Sharing group's local instance ID, or Sharing group's global UUID @@ -2123,7 +2123,7 @@ class PyMISP: return self._check_json_response(response) def add_server_to_sharing_group(self, sharing_group: MISPSharingGroup | int | str | UUID, - server: MISPServer | int | str | UUID, all_orgs: bool = False) -> dict: + server: MISPServer | int | str | UUID, all_orgs: bool = False) -> dict[str, Any]: '''Add a server to a sharing group: https://www.misp-project.org/openapi/#tag/Sharing-Groups/operation/addServerToSharingGroup :param sharing_group: Sharing group's local instance ID, or Sharing group's global UUID @@ -2137,7 +2137,7 @@ class PyMISP: return self._check_json_response(response) def remove_server_from_sharing_group(self, sharing_group: MISPSharingGroup | int | str | UUID, - server: MISPServer | int | str | UUID) -> dict: + server: MISPServer | int | str | UUID) -> dict[str, Any]: '''Remove a server from a sharing group: https://www.misp-project.org/openapi/#tag/Sharing-Groups/operation/removeServerFromSharingGroup :param sharing_group: Sharing group's local instance ID, or Sharing group's global UUID @@ -2153,7 +2153,7 @@ class PyMISP: # ## BEGIN Organisation ### - def organisations(self, scope="local", search: str | None = None, pythonify: bool = False) -> dict | list[MISPOrganisation]: + def organisations(self, scope: str="local", search: str | None = None, pythonify: bool = False) -> dict[str, Any] | list[MISPOrganisation] | list[dict[str, Any]]: """Get all the organisations: https://www.misp-project.org/openapi/#tag/Organisations/operation/getOrganisations :param scope: scope of organizations to get @@ -2165,8 +2165,8 @@ class PyMISP: url_path += f"/searchall:{search}" r = self._prepare_request('GET', url_path) - organisations = self._check_json_response(r) - if not (self.global_pythonify or pythonify) or 'errors' in organisations: + organisations = self._check_json_response_list(r) + if not (self.global_pythonify or pythonify) or isinstance(organisations, dict): return organisations to_return = [] for organisation in organisations: @@ -2175,7 +2175,7 @@ class PyMISP: to_return.append(o) return to_return - def get_organisation(self, organisation: MISPOrganisation | int | str | UUID, pythonify: bool = False) -> dict | MISPOrganisation: + def get_organisation(self, organisation: MISPOrganisation | int | str | UUID, pythonify: bool = False) -> dict[str, Any] | MISPOrganisation: """Get an organisation by id: https://www.misp-project.org/openapi/#tag/Organisations/operation/getOrganisationById :param organisation: organization to get @@ -2199,7 +2199,7 @@ class PyMISP: r = self._prepare_request('HEAD', f'organisations/view/{organisation_id}') return self._check_head_response(r) - def add_organisation(self, organisation: MISPOrganisation, pythonify: bool = False) -> dict | MISPOrganisation: + def add_organisation(self, organisation: MISPOrganisation, pythonify: bool = False) -> dict[str, Any] | MISPOrganisation: """Add an organisation: https://www.misp-project.org/openapi/#tag/Organisations/operation/addOrganisation :param organisation: organization to add @@ -2213,7 +2213,7 @@ class PyMISP: o.from_dict(**new_organisation) return o - def update_organisation(self, organisation: MISPOrganisation, organisation_id: int | None = None, pythonify: bool = False) -> dict | MISPOrganisation: + def update_organisation(self, organisation: MISPOrganisation, organisation_id: int | None = None, pythonify: bool = False) -> dict[str, Any] | MISPOrganisation: """Update an organisation: https://www.misp-project.org/openapi/#tag/Organisations/operation/editOrganisation :param organisation: organization to update @@ -2232,7 +2232,7 @@ class PyMISP: o.from_dict(**organisation) return o - def delete_organisation(self, organisation: MISPOrganisation | int | str | UUID) -> dict: + def delete_organisation(self, organisation: MISPOrganisation | int | str | UUID) -> dict[str, Any]: """Delete an organisation by id: https://www.misp-project.org/openapi/#tag/Organisations/operation/deleteOrganisation :param organisation: organization to delete @@ -2246,7 +2246,7 @@ class PyMISP: # ## BEGIN User ### - def users(self, search: str | None = None, organisation: int | None = None, pythonify: bool = False) -> dict | list[MISPUser]: + def users(self, search: str | None = None, organisation: int | None = None, pythonify: bool = False) -> dict[str, Any] | list[MISPUser] | list[dict[str, Any]]: """Get all the users, or a filtered set of users: https://www.misp-project.org/openapi/#tag/Users/operation/getUsers :param search: The search to make against the list of users @@ -2260,8 +2260,8 @@ class PyMISP: organisation_id = get_uuid_or_id_from_abstract_misp(organisation) urlpath += f"/searchorg:{organisation_id}" r = self._prepare_request('GET', urlpath) - users = self._check_json_response(r) - if not (self.global_pythonify or pythonify) or 'errors' in users: + users = self._check_json_response_list(r) + if not (self.global_pythonify or pythonify) or isinstance(users, dict): return users to_return = [] for user in users: @@ -2270,7 +2270,7 @@ class PyMISP: to_return.append(u) return to_return - def get_user(self, user: MISPUser | int | str | UUID = 'me', pythonify: bool = False, expanded: bool = False) -> dict | MISPUser | tuple[MISPUser, MISPRole, list[MISPUserSetting]]: + def get_user(self, user: MISPUser | int | str | UUID = 'me', pythonify: bool = False, expanded: bool = False) -> dict[str, Any] | MISPUser | tuple[MISPUser, MISPRole, list[MISPUserSetting]]: """Get a user by id: https://www.misp-project.org/openapi/#tag/Users/operation/getUsers :param user: user to get; `me` means the owner of the API key doing the query @@ -2310,7 +2310,7 @@ class PyMISP: else: raise PyMISPUnexpectedResponse(f'Unable to get authkey: {authkey}') - def add_user(self, user: MISPUser, pythonify: bool = False) -> dict | MISPUser: + def add_user(self, user: MISPUser, pythonify: bool = False) -> dict[str, Any] | MISPUser: """Add a new user: https://www.misp-project.org/openapi/#tag/Users/operation/addUser :param user: user to add @@ -2324,7 +2324,7 @@ class PyMISP: u.from_dict(**user_j) return u - def update_user(self, user: MISPUser, user_id: int | None = None, pythonify: bool = False) -> dict | MISPUser: + def update_user(self, user: MISPUser, user_id: int | None = None, pythonify: bool = False) -> dict[str, Any] | MISPUser: """Update a user on a MISP instance: https://www.misp-project.org/openapi/#tag/Users/operation/editUser :param user: user to update @@ -2346,7 +2346,7 @@ class PyMISP: e.from_dict(**updated_user) return e - def delete_user(self, user: MISPUser | int | str | UUID) -> dict: + def delete_user(self, user: MISPUser | int | str | UUID) -> dict[str, Any]: """Delete a user by id: https://www.misp-project.org/openapi/#tag/Users/operation/deleteUser :param user: user to delete @@ -2356,7 +2356,7 @@ class PyMISP: response = self._prepare_request('POST', f'admin/users/delete/{user_id}') return self._check_json_response(response) - def change_user_password(self, new_password: str) -> dict: + def change_user_password(self, new_password: str) -> dict[str, Any]: """Change the password of the curent user: :param new_password: password to set @@ -2364,14 +2364,14 @@ class PyMISP: response = self._prepare_request('POST', 'users/change_pw', data={'password': new_password}) return self._check_json_response(response) - def user_registrations(self, pythonify: bool = False) -> dict | list[MISPInbox]: + def user_registrations(self, pythonify: bool = False) -> dict[str, Any] | list[MISPInbox] | list[dict[str, Any]]: """Get all the user registrations :param pythonify: Returns a list of PyMISP Objects instead of the plain json output. Warning: it might use a lot of RAM """ r = self._prepare_request('GET', 'users/registrations/index') - registrations = self._check_json_response(r) - if not (self.global_pythonify or pythonify) or 'errors' in registrations: + registrations = self._check_json_response_list(r) + if not (self.global_pythonify or pythonify) or isinstance(registrations, dict): return registrations to_return = [] for registration in registrations: @@ -2383,8 +2383,9 @@ class PyMISP: def accept_user_registration(self, registration: MISPInbox | int | str | UUID, organisation: MISPOrganisation | int | str | UUID | None = None, role: MISPRole | int | str | None = None, - perm_sync: bool = False, perm_publish: bool = False, perm_admin: bool = False, - unsafe_fallback: bool = False): + perm_sync: bool = False, perm_publish: bool = False, + perm_admin: bool = False, + unsafe_fallback: bool = False) -> dict[str, Any]: """Accept a user registration :param registration: the registration to accept @@ -2399,11 +2400,11 @@ class PyMISP: if role: role_id = role_id = get_uuid_or_id_from_abstract_misp(role) else: - for role in self.roles(pythonify=True): - if not isinstance(role, MISPRole): + for _r in self.roles(pythonify=True): + if not isinstance(_r, MISPRole): continue - if role.default_role: # type: ignore - role_id = get_uuid_or_id_from_abstract_misp(role) + if _r.default_role: # type: ignore + role_id = get_uuid_or_id_from_abstract_misp(_r) break else: raise PyMISPError('Unable to find default role') @@ -2431,7 +2432,7 @@ class PyMISP: r = self._prepare_request('POST', f'users/acceptRegistrations/{registration_id}', data=to_post) return self._check_json_response(r) - def discard_user_registration(self, registration: MISPInbox | int | str | UUID): + def discard_user_registration(self, registration: MISPInbox | int | str | UUID) -> dict[str, Any]: """Discard a user registration :param registration: the registration to discard @@ -2444,14 +2445,14 @@ class PyMISP: # ## BEGIN Role ### - def roles(self, pythonify: bool = False) -> dict | list[MISPRole]: + def roles(self, pythonify: bool = False) -> dict[str, Any] | list[MISPRole] | list[dict[str, Any]]: """Get the existing roles :param pythonify: Returns a list of PyMISP Objects instead of the plain json output. Warning: it might use a lot of RAM """ r = self._prepare_request('GET', 'roles/index') - roles = self._check_json_response(r) - if not (self.global_pythonify or pythonify) or 'errors' in roles: + roles = self._check_json_response_list(r) + if not (self.global_pythonify or pythonify) or isinstance(roles, dict): return roles to_return = [] for role in roles: @@ -2460,7 +2461,7 @@ class PyMISP: to_return.append(nr) return to_return - def set_default_role(self, role: MISPRole | int | str | UUID) -> dict: + def set_default_role(self, role: MISPRole | int | str | UUID) -> dict[str, Any]: """Set a default role for the new user accounts :param role: the default role to set @@ -2474,19 +2475,19 @@ class PyMISP: # ## BEGIN Decaying Models ### - def update_decaying_models(self) -> dict: + def update_decaying_models(self) -> dict[str, Any]: """Update all the Decaying models""" response = self._prepare_request('POST', 'decayingModel/update') return self._check_json_response(response) - def decaying_models(self, pythonify: bool = False) -> dict | list[MISPDecayingModel]: + def decaying_models(self, pythonify: bool = False) -> dict[str, Any] | list[MISPDecayingModel] | list[dict[str, Any]]: """Get all the decaying models :param pythonify: Returns a list of PyMISP Objects instead of the plain json output """ r = self._prepare_request('GET', 'decayingModel/index') - models = self._check_json_response(r) - if not (self.global_pythonify or pythonify) or 'errors' in models: + models = self._check_json_response_list(r) + if not (self.global_pythonify or pythonify) or isinstance(models, dict): return models to_return = [] for model in models: @@ -2495,7 +2496,7 @@ class PyMISP: to_return.append(n) return to_return - def enable_decaying_model(self, decaying_model: MISPDecayingModel | int | str) -> dict: + def enable_decaying_model(self, decaying_model: MISPDecayingModel | int | str) -> dict[str, Any]: """Enable a decaying Model""" if isinstance(decaying_model, MISPDecayingModel): decaying_model_id = decaying_model.id @@ -2504,7 +2505,7 @@ class PyMISP: response = self._prepare_request('POST', f'decayingModel/enable/{decaying_model_id}') return self._check_json_response(response) - def disable_decaying_model(self, decaying_model: MISPDecayingModel | int | str) -> dict: + def disable_decaying_model(self, decaying_model: MISPDecayingModel | int | str) -> dict[str, Any]: """Disable a decaying Model""" if isinstance(decaying_model, MISPDecayingModel): decaying_model_id = decaying_model.id @@ -2517,7 +2518,7 @@ class PyMISP: # ## BEGIN Search methods ### - def search(self, controller: str = 'events', return_format: str = 'json', + def search(self, controller: str = 'events', return_format: str = 'json', # type: ignore[no-untyped-def] limit: int | None = None, page: int | None = None, value: SearchParameterTypes | None = None, type_attribute: SearchParameterTypes | None = None, @@ -2564,7 +2565,7 @@ class PyMISP: exclude_decayed: bool | None = None, sharinggroup: int | list[int] | None = None, pythonify: bool | None = False, - **kwargs) -> dict | str | list[MISPEvent | MISPAttribute | MISPObject]: + **kwargs) -> dict[str, Any] | str | list[MISPEvent | MISPAttribute | MISPObject] | list[dict[str, Any]]: '''Search in the MISP instance :param controller: Controller to search on, it can be `events`, `objects`, `attributes`. The response will either be a list of events, objects, or attributes. @@ -2730,6 +2731,7 @@ class PyMISP: elif return_format not in ['json', 'yara-json']: return self._check_response(response) + # This one is truly fucked: event returns a list, attributes doesn't. normalized_response = self._check_json_response(response) if 'errors' in normalized_response: @@ -2739,6 +2741,8 @@ class PyMISP: # The response is in json, we can convert it to a list of pythonic MISP objects to_return: list[MISPEvent | MISPAttribute | MISPObject] = [] if controller == 'events': + if isinstance(normalized_response, dict): + return normalized_response for e in normalized_response: me = MISPEvent() me.load(e) @@ -2772,6 +2776,8 @@ class PyMISP: ma.Sighting = sightings to_return.append(ma) elif controller == 'objects': + if isinstance(normalized_response, dict): + return normalized_response for o in normalized_response: mo = MISPObject(o['Object']['name']) mo.from_dict(**o) @@ -2809,7 +2815,7 @@ class PyMISP: desc: bool | None = None, limit: int | None = None, page: int | None = None, - pythonify: bool | None = None) -> dict | list[MISPEvent]: + pythonify: bool | None = None) -> dict[str, Any] | list[MISPEvent] | list[dict[str, Any]]: """Search event metadata shown on the event index page. Using ! in front of a value means NOT, except for parameters date_from, date_to and timestamp which cannot be negated. Criteria are AND-ed together; values in lists are OR-ed together. Return matching events @@ -2866,9 +2872,9 @@ class PyMISP: query["direction"] = "desc" if desc else "asc" url = urljoin(self.root_url, 'events/index') response = self._prepare_request('POST', url, data=query) - normalized_response = self._check_json_response(response) + normalized_response = self._check_json_response_list(response) - if not (self.global_pythonify or pythonify): + if not (self.global_pythonify or pythonify) or isinstance(normalized_response, dict): return normalized_response to_return = [] for e_meta in normalized_response: @@ -2895,7 +2901,7 @@ class PyMISP: include_attribute: bool | None = None, include_event_meta: bool | None = None, pythonify: bool | None = False - ) -> dict | list[dict[str, MISPEvent | MISPAttribute | MISPSighting]]: + ) -> dict[str, Any] | list[dict[str, MISPEvent | MISPAttribute | MISPSighting]]: '''Search sightings :param context: The context of the search. Can be either "attribute", "event", or nothing (will then match on events and attributes). @@ -2942,8 +2948,8 @@ class PyMISP: url = urljoin(self.root_url, url_path) response = self._prepare_request('POST', url, data=query) - normalized_response = self._check_json_response(response) - if not (self.global_pythonify or pythonify) or 'errors' in normalized_response: + normalized_response = self._check_json_response_list(response) + if not (self.global_pythonify or pythonify) or isinstance(normalized_response, dict): return normalized_response if self.global_pythonify or pythonify: @@ -2974,7 +2980,7 @@ class PyMISP: action: str | None = None, user_id: int | None = None, change: str | None = None, email: str | None = None, org: str | None = None, description: str | None = None, - ip: str | None = None, pythonify: bool | None = False) -> dict | list[MISPLog]: + ip: str | None = None, pythonify: bool | None = False) -> dict[str, Any] | list[MISPLog] | list[dict[str, Any]]: '''Search in logs Note: to run substring queries simply append/prepend/encapsulate the search term with % @@ -3003,8 +3009,8 @@ class PyMISP: query['created'] = query.pop('created').timestamp() response = self._prepare_request('POST', 'admin/logs/index', data=query) - normalized_response = self._check_json_response(response) - if not (self.global_pythonify or pythonify) or 'errors' in normalized_response: + normalized_response = self._check_json_response_list(response) + if not (self.global_pythonify or pythonify) or isinstance(normalized_response, dict): return normalized_response to_return = [] @@ -3014,11 +3020,11 @@ class PyMISP: to_return.append(ml) return to_return - def search_feeds(self, value: SearchParameterTypes | None = None, pythonify: bool | None = False) -> dict | list[MISPFeed]: + def search_feeds(self, value: SearchParameterTypes | None = None, pythonify: bool | None = False) -> dict[str, Any] | list[MISPFeed] | list[dict[str, Any]]: '''Search in the feeds cached on the servers''' response = self._prepare_request('POST', 'feeds/searchCaches', data={'value': value}) - normalized_response = self._check_json_response(response) - if not (self.global_pythonify or pythonify) or 'errors' in normalized_response: + normalized_response = self._check_json_response_list(response) + if not (self.global_pythonify or pythonify) or isinstance(normalized_response, dict): return normalized_response to_return = [] for feed in normalized_response: @@ -3031,14 +3037,14 @@ class PyMISP: # ## BEGIN Communities ### - def communities(self, pythonify: bool = False) -> dict | list[MISPCommunity]: + def communities(self, pythonify: bool = False) -> dict[str, Any] | list[MISPCommunity] | list[dict[str, Any]]: """Get all the communities :param pythonify: Returns a list of PyMISP Objects instead of the plain json output. Warning: it might use a lot of RAM """ r = self._prepare_request('GET', 'communities/index') - communities = self._check_json_response(r) - if not (self.global_pythonify or pythonify) or 'errors' in communities: + communities = self._check_json_response_list(r) + if not (self.global_pythonify or pythonify) or isinstance(communities, dict): return communities to_return = [] for community in communities: @@ -3047,7 +3053,7 @@ class PyMISP: to_return.append(c) return to_return - def get_community(self, community: MISPCommunity | int | str | UUID, pythonify: bool = False) -> dict | MISPCommunity: + def get_community(self, community: MISPCommunity | int | str | UUID, pythonify: bool = False) -> dict[str, Any] | MISPCommunity: """Get a community by id from a MISP instance :param community: community to get @@ -3070,7 +3076,7 @@ class PyMISP: requestor_organisation_description: str | None = None, message: str | None = None, sync: bool = False, anonymise_requestor_server: bool = False, - mock: bool = False) -> dict: + mock: bool = False) -> dict[str, Any]: """Request the access to a community :param community: community to request access @@ -3098,14 +3104,14 @@ class PyMISP: # ## BEGIN Event Delegation ### - def event_delegations(self, pythonify: bool = False) -> dict | list[MISPEventDelegation]: + def event_delegations(self, pythonify: bool = False) -> dict[str, Any] | list[MISPEventDelegation] | list[dict[str, Any]]: """Get all the event delegations :param pythonify: Returns a list of PyMISP Objects instead of the plain json output. Warning: it might use a lot of RAM """ r = self._prepare_request('GET', 'eventDelegations') - delegations = self._check_json_response(r) - if not (self.global_pythonify or pythonify) or 'errors' in delegations: + delegations = self._check_json_response_list(r) + if not (self.global_pythonify or pythonify) or isinstance(delegations, dict): return delegations to_return = [] for delegation in delegations: @@ -3114,7 +3120,7 @@ class PyMISP: to_return.append(d) return to_return - def accept_event_delegation(self, delegation: MISPEventDelegation | int | str, pythonify: bool = False) -> dict: + def accept_event_delegation(self, delegation: MISPEventDelegation | int | str, pythonify: bool = False) -> dict[str, Any]: """Accept the delegation of an event :param delegation: event delegation to accept @@ -3124,7 +3130,7 @@ class PyMISP: r = self._prepare_request('POST', f'eventDelegations/acceptDelegation/{delegation_id}') return self._check_json_response(r) - def discard_event_delegation(self, delegation: MISPEventDelegation | int | str, pythonify: bool = False) -> dict: + def discard_event_delegation(self, delegation: MISPEventDelegation | int | str, pythonify: bool = False) -> dict[str, Any]: """Discard the delegation of an event :param delegation: event delegation to discard @@ -3137,7 +3143,7 @@ class PyMISP: def delegate_event(self, event: MISPEvent | int | str | UUID | None = None, organisation: MISPOrganisation | int | str | UUID | None = None, event_delegation: MISPEventDelegation | None = None, - distribution: int = -1, message: str = '', pythonify: bool = False) -> dict | MISPEventDelegation: + distribution: int = -1, message: str = '', pythonify: bool = False) -> dict[str, Any] | MISPEventDelegation: """Delegate an event. Either event and organisation OR event_delegation are required :param event: event to delegate @@ -3167,7 +3173,7 @@ class PyMISP: # ## BEGIN Others ### - def push_event_to_ZMQ(self, event: MISPEvent | int | str | UUID) -> dict: + def push_event_to_ZMQ(self, event: MISPEvent | int | str | UUID) -> dict[str, Any]: """Force push an event by id on ZMQ :param event: the event to push @@ -3176,7 +3182,7 @@ class PyMISP: response = self._prepare_request('POST', f'events/pushEventToZMQ/{event_id}.json') return self._check_json_response(response) - def direct_call(self, url: str, data: dict | None = None, params: Mapping = {}, kw_params: Mapping = {}) -> Any: + def direct_call(self, url: str, data: dict[str, Any] | None = None, params: Mapping[str, Any] = {}, kw_params: Mapping[str, Any] = {}) -> Any: """Very lightweight call that posts a data blob (python dictionary or json string) on the URL :param url: URL to post to @@ -3190,8 +3196,8 @@ class PyMISP: response = self._prepare_request('POST', url, data=data, params=params, kw_params=kw_params) return self._check_response(response, lenient_response_type=True) - def freetext(self, event: MISPEvent | int | str | UUID, string: str, adhereToWarninglists: bool | str = False, - distribution: int | None = None, returnMetaAttributes: bool = False, pythonify: bool = False, **kwargs) -> dict | list[MISPAttribute]: + def freetext(self, event: MISPEvent | int | str | UUID, string: str, adhereToWarninglists: bool | str = False, # type: ignore[no-untyped-def] + distribution: int | None = None, returnMetaAttributes: bool = False, pythonify: bool = False, **kwargs) -> dict[str, Any] | list[MISPAttribute] | list[dict[str, Any]]: """Pass a text to the freetext importer :param event: event @@ -3215,8 +3221,8 @@ class PyMISP: if returnMetaAttributes: query['returnMetaAttributes'] = returnMetaAttributes r = self._prepare_request('POST', f'events/freeTextImport/{event_id}', data=query, **kwargs) - attributes = self._check_json_response(r) - if returnMetaAttributes or not (self.global_pythonify or pythonify) or 'errors' in attributes: + attributes = self._check_json_response_list(r) + if returnMetaAttributes or not (self.global_pythonify or pythonify) or isinstance(attributes, dict): return attributes to_return = [] for attribute in attributes: @@ -3225,7 +3231,8 @@ class PyMISP: to_return.append(a) return to_return - def upload_stix(self, path: str | Path | BytesIO | StringIO | None = None, data: str | bytes | None = None, version: str = '2'): + def upload_stix(self, path: str | Path | BytesIO | StringIO | None = None, + data: str | bytes | None = None, version: str = '2') -> requests.Response: """Upload a STIX file to MISP. :param path: Path to the STIX on the disk (can be a path-like object, or a pseudofile) @@ -3256,7 +3263,7 @@ class PyMISP: # ## BEGIN Statistics ### - def attributes_statistics(self, context: str = 'type', percentage: bool = False) -> dict: + def attributes_statistics(self, context: str = 'type', percentage: bool = False) -> dict[str, Any]: """Get attribute statistics from the MISP instance :param context: "type" or "category" @@ -3272,7 +3279,7 @@ class PyMISP: response = self._prepare_request('GET', path) return self._check_json_response(response) - def tags_statistics(self, percentage: bool = False, name_sort: bool = False) -> dict: + def tags_statistics(self, percentage: bool = False, name_sort: bool = False) -> dict[str, Any]: """Get tag statistics from the MISP instance :param percentage: get percentages @@ -3291,7 +3298,7 @@ class PyMISP: response = self._prepare_request('GET', f'tags/tagStatistics/{p}/{ns}') return self._check_json_response(response) - def users_statistics(self, context: str = 'data') -> dict: + def users_statistics(self, context: str = 'data') -> dict[str, Any]: """Get user statistics from the MISP instance :param context: one of 'data', 'orgs', 'users', 'tags', 'attributehistogram', 'sightings', 'galaxyMatrix' @@ -3306,14 +3313,14 @@ class PyMISP: # ## BEGIN User Settings ### - def user_settings(self, pythonify: bool = False) -> dict | list[MISPUserSetting]: + def user_settings(self, pythonify: bool = False) -> dict[str, Any] | list[MISPUserSetting] | list[dict[str, Any]]: """Get all the user settings: https://www.misp-project.org/openapi/#tag/UserSettings/operation/getUserSettings :param pythonify: Returns a list of PyMISP Objects instead of the plain json output. Warning: it might use a lot of RAM """ r = self._prepare_request('GET', 'userSettings/index') - user_settings = self._check_json_response(r) - if not (self.global_pythonify or pythonify) or 'errors' in user_settings: + user_settings = self._check_json_response_list(r) + if not (self.global_pythonify or pythonify) or isinstance(user_settings, dict): return user_settings to_return = [] for user_setting in user_settings: @@ -3323,7 +3330,7 @@ class PyMISP: return to_return def get_user_setting(self, user_setting: str, user: MISPUser | int | str | UUID | None = None, - pythonify: bool = False) -> dict | MISPUserSetting: + pythonify: bool = False) -> dict[str, Any] | MISPUserSetting: """Get a user setting: https://www.misp-project.org/openapi/#tag/UserSettings/operation/getUserSettingById :param user_setting: name of user setting @@ -3341,8 +3348,8 @@ class PyMISP: u.from_dict(**user_setting_j) return u - def set_user_setting(self, user_setting: str, value: str | dict, user: MISPUser | int | str | UUID | None = None, - pythonify: bool = False) -> dict | MISPUserSetting: + def set_user_setting(self, user_setting: str, value: str | dict[str, Any], user: MISPUser | int | str | UUID | None = None, + pythonify: bool = False) -> dict[str, Any] | MISPUserSetting: """Set a user setting: https://www.misp-project.org/openapi/#tag/UserSettings/operation/setUserSetting :param user_setting: name of user setting @@ -3364,7 +3371,7 @@ class PyMISP: u.from_dict(**user_setting_j) return u - def delete_user_setting(self, user_setting: str, user: MISPUser | int | str | UUID | None = None) -> dict: + def delete_user_setting(self, user_setting: str, user: MISPUser | int | str | UUID | None = None) -> dict[str, Any]: """Delete a user setting: https://www.misp-project.org/openapi/#tag/UserSettings/operation/deleteUserSettingById :param user_setting: name of user setting @@ -3380,14 +3387,14 @@ class PyMISP: # ## BEGIN Blocklists ### - def event_blocklists(self, pythonify: bool = False) -> dict | list[MISPEventBlocklist]: + def event_blocklists(self, pythonify: bool = False) -> dict[str, Any] | list[MISPEventBlocklist] | list[dict[str, Any]]: """Get all the blocklisted events :param pythonify: Returns a list of PyMISP Objects instead of the plain json output. Warning: it might use a lot of RAM """ r = self._prepare_request('GET', 'eventBlocklists/index') - event_blocklists = self._check_json_response(r) - if not (self.global_pythonify or pythonify) or 'errors' in event_blocklists: + event_blocklists = self._check_json_response_list(r) + if not (self.global_pythonify or pythonify) or isinstance(event_blocklists, dict): return event_blocklists to_return = [] for event_blocklist in event_blocklists: @@ -3396,14 +3403,14 @@ class PyMISP: to_return.append(ebl) return to_return - def organisation_blocklists(self, pythonify: bool = False) -> dict | list[MISPOrganisationBlocklist]: + def organisation_blocklists(self, pythonify: bool = False) -> dict[str, Any] | list[MISPOrganisationBlocklist] | list[dict[str, Any]]: """Get all the blocklisted organisations :param pythonify: Returns a list of PyMISP Objects instead of the plain json output. Warning: it might use a lot of RAM """ r = self._prepare_request('GET', 'orgBlocklists/index') - organisation_blocklists = self._check_json_response(r) - if not (self.global_pythonify or pythonify) or 'errors' in organisation_blocklists: + organisation_blocklists = self._check_json_response_list(r) + if not (self.global_pythonify or pythonify) or isinstance(organisation_blocklists, dict): return organisation_blocklists to_return = [] for organisation_blocklist in organisation_blocklists: @@ -3412,7 +3419,7 @@ class PyMISP: to_return.append(obl) return to_return - def _add_entries_to_blocklist(self, blocklist_type: str, uuids: str | list[str], **kwargs) -> dict: + def _add_entries_to_blocklist(self, blocklist_type: str, uuids: str | list[str], **kwargs) -> dict[str, Any]: # type: ignore[no-untyped-def] if blocklist_type == 'event': url = 'eventBlocklists/add' elif blocklist_type == 'organisation': @@ -3428,7 +3435,7 @@ class PyMISP: return self._check_json_response(r) def add_event_blocklist(self, uuids: str | list[str], comment: str | None = None, - event_info: str | None = None, event_orgc: str | None = None) -> dict: + event_info: str | None = None, event_orgc: str | None = None) -> dict[str, Any]: """Add a new event in the blocklist :param uuids: UUIDs @@ -3439,7 +3446,7 @@ class PyMISP: return self._add_entries_to_blocklist('event', uuids=uuids, comment=comment, event_info=event_info, event_orgc=event_orgc) def add_organisation_blocklist(self, uuids: str | list[str], comment: str | None = None, - org_name: str | None = None) -> dict: + org_name: str | None = None) -> dict[str, Any]: """Add a new organisation in the blocklist :param uuids: UUIDs @@ -3448,7 +3455,7 @@ class PyMISP: """ return self._add_entries_to_blocklist('organisation', uuids=uuids, comment=comment, org_name=org_name) - def _update_entries_in_blocklist(self, blocklist_type: str, uuid, **kwargs) -> dict: + def _update_entries_in_blocklist(self, blocklist_type: str, uuid, **kwargs) -> dict[str, Any]: # type: ignore[no-untyped-def] if blocklist_type == 'event': url = f'eventBlocklists/edit/{uuid}' elif blocklist_type == 'organisation': @@ -3459,7 +3466,7 @@ class PyMISP: r = self._prepare_request('POST', url, data=data) return self._check_json_response(r) - def update_event_blocklist(self, event_blocklist: MISPEventBlocklist, event_blocklist_id: int | str | UUID | None = None, pythonify: bool = False) -> dict | MISPEventBlocklist: + def update_event_blocklist(self, event_blocklist: MISPEventBlocklist, event_blocklist_id: int | str | UUID | None = None, pythonify: bool = False) -> dict[str, Any] | MISPEventBlocklist: """Update an event in the blocklist :param event_blocklist: event block list @@ -3477,7 +3484,7 @@ class PyMISP: e.from_dict(**updated_event_blocklist) return e - def update_organisation_blocklist(self, organisation_blocklist: MISPOrganisationBlocklist, organisation_blocklist_id: int | str | UUID | None = None, pythonify: bool = False) -> dict | MISPOrganisationBlocklist: + def update_organisation_blocklist(self, organisation_blocklist: MISPOrganisationBlocklist, organisation_blocklist_id: int | str | UUID | None = None, pythonify: bool = False) -> dict[str, Any] | MISPOrganisationBlocklist: """Update an organisation in the blocklist :param organisation_blocklist: organization block list @@ -3495,7 +3502,7 @@ class PyMISP: o.from_dict(**updated_organisation_blocklist) return o - def delete_event_blocklist(self, event_blocklist: MISPEventBlocklist | str | UUID) -> dict: + def delete_event_blocklist(self, event_blocklist: MISPEventBlocklist | str | UUID) -> dict[str, Any]: """Delete a blocklisted event by id :param event_blocklist: event block list to delete @@ -3504,7 +3511,7 @@ class PyMISP: response = self._prepare_request('POST', f'eventBlocklists/delete/{event_blocklist_id}') return self._check_json_response(response) - def delete_organisation_blocklist(self, organisation_blocklist: MISPOrganisationBlocklist | str | UUID) -> dict: + def delete_organisation_blocklist(self, organisation_blocklist: MISPOrganisationBlocklist | str | UUID) -> dict[str, Any]: """Delete a blocklisted organisation by id :param organisation_blocklist: organization block list to delete @@ -3517,7 +3524,8 @@ class PyMISP: # ## BEGIN Global helpers ### - def change_sharing_group_on_entity(self, misp_entity: MISPEvent | MISPAttribute | MISPObject, sharing_group_id, pythonify: bool = False) -> dict | MISPEvent | MISPObject | MISPAttribute | MISPShadowAttribute: + def change_sharing_group_on_entity(self, misp_entity: MISPEvent | MISPAttribute | MISPObject, + sharing_group_id: int, pythonify: bool = False) -> dict[str, Any] | MISPEvent | MISPObject | MISPAttribute | MISPShadowAttribute: """Change the sharing group of an event, an attribute, or an object :param misp_entity: entity to change @@ -3539,8 +3547,8 @@ class PyMISP: raise PyMISPError('The misp_entity must be MISPEvent, MISPObject or MISPAttribute') - def tag(self, misp_entity: AbstractMISP | str | dict, tag: MISPTag | str, - local: bool = False, relationship_type: str | None = None) -> dict: + def tag(self, misp_entity: AbstractMISP | str | dict[str, Any], tag: MISPTag | str, + local: bool = False, relationship_type: str | None = None) -> dict[str, Any]: """Tag an event or an attribute. :param misp_entity: a MISPEvent, a MISP Attribute, or a UUID @@ -3559,7 +3567,7 @@ class PyMISP: response = self._prepare_request('POST', 'tags/attachTagToObject', data=to_post) return self._check_json_response(response) - def untag(self, misp_entity: AbstractMISP | str | dict, tag: MISPTag | str) -> dict: + def untag(self, misp_entity: AbstractMISP | str | dict[str, Any], tag: MISPTag | str) -> dict[str, Any]: """Untag an event or an attribute :param misp_entity: misp_entity can be a UUID @@ -3600,7 +3608,7 @@ class PyMISP: # ## MISP internal tasks ### - def get_all_functions(self, not_implemented: bool = False): + def get_all_functions(self, not_implemented: bool = False) -> list[str]: '''Get all methods available via the API, including ones that are not implemented.''' response = self._prepare_request('GET', 'servers/queryACL/printAllFunctionNames') functions = self._check_json_response(response) @@ -3617,7 +3625,7 @@ class PyMISP: paths.append(path) if not not_implemented: - return path + return [str(path)] with open(__file__) as f: content = f.read() @@ -3631,7 +3639,7 @@ class PyMISP: # ## Internal methods ### - def _old_misp(self, minimal_version_required: tuple, removal_date: str | date | datetime, method: str | None = None, message: str | None = None) -> bool: + def _old_misp(self, minimal_version_required: tuple[int], removal_date: str | date | datetime, method: str | None = None, message: str | None = None) -> bool: if self._misp_version >= minimal_version_required: return False if isinstance(removal_date, (datetime, date)): @@ -3669,11 +3677,21 @@ class PyMISP: return value return value - def _check_json_response(self, response: requests.Response) -> dict: # type: ignore + def _check_json_response_list(self, response: requests.Response) -> dict[str, Any] | list[dict[str, Any]]: r = self._check_response(response, expect_json=True) - if isinstance(r, (dict, list)): + if isinstance(r, dict) and 'errors' in r: + return r + if isinstance(r, list): return r # Else: an exception was raised anyway + raise PyMISPUnexpectedResponse(f'A list was expected, got a {type(r)}: {r}') + + def _check_json_response(self, response: requests.Response) -> dict[str, Any]: + r = self._check_response(response, expect_json=True) + if isinstance(r, dict): + return r + # Else: an exception was raised anyway + raise PyMISPUnexpectedResponse(f'A dict was expected, got a string: {r}') def _check_head_response(self, response: requests.Response) -> bool: if response.status_code == 200: @@ -3683,7 +3701,7 @@ class PyMISP: else: raise MISPServerError(f'Error code {response.status_code} for HEAD request') - def _check_response(self, response: requests.Response, lenient_response_type: bool = False, expect_json: bool = False) -> dict | str: + def _check_response(self, response: requests.Response, lenient_response_type: bool = False, expect_json: bool = False) -> dict[str, Any] | str: """Check if the response from the server is not an unexpected error""" if response.status_code >= 500: headers_without_auth = {i: response.request.headers[i] for i in response.request.headers if i != 'Authorization'} @@ -3722,11 +3740,11 @@ class PyMISP: return {'errors': 'The response is empty.'} return response.text - def __repr__(self): + def __repr__(self) -> str: return f'<{self.__class__.__name__}(url={self.root_url})' - def _prepare_request(self, request_type: str, url: str, data: Iterable | Mapping | AbstractMISP | bytes | None = None, - params: Mapping = {}, kw_params: Mapping = {}, + def _prepare_request(self, request_type: str, url: str, data: Iterable[Any] | Mapping[str, Any] | AbstractMISP | bytes | None = None, + params: Mapping[str, Any] = {}, kw_params: Mapping[str, Any] = {}, output_type: str = 'json', content_type: str = 'json') -> requests.Response: '''Prepare a request for python-requests''' if url[0] == '/': @@ -3769,7 +3787,7 @@ class PyMISP: verify=self.ssl, cert=self.cert) return self.__session.send(prepped, timeout=self.timeout, **settings) - def _csv_to_dict(self, csv_content: str) -> list[dict]: + def _csv_to_dict(self, csv_content: str) -> list[dict[str, Any]]: '''Makes a list of dict out of a csv file (requires headers)''' fieldnames, lines = csv_content.split('\n', 1) fields = fieldnames.split(',') diff --git a/pymisp/exceptions.py b/pymisp/exceptions.py index 2479bec..a0dd736 100644 --- a/pymisp/exceptions.py +++ b/pymisp/exceptions.py @@ -2,7 +2,7 @@ from __future__ import annotations class PyMISPError(Exception): - def __init__(self, message): + def __init__(self, message: str) -> None: super().__init__(message) self.message = message diff --git a/pymisp/mispevent.py b/pymisp/mispevent.py index 899fadc..ac1361c 100644 --- a/pymisp/mispevent.py +++ b/pymisp/mispevent.py @@ -35,22 +35,8 @@ try: except ImportError: logger.exception("Cannot import dateutil") -try: - # pyme renamed to gpg the 2016-10-28 - import gpg # type: ignore - from gpg.constants.sig import mode # type: ignore - has_pyme = True -except ImportError: - try: - # pyme renamed to gpg the 2016-10-28 - import pyme as gpg # type: ignore - from pyme.constants.sig import mode # type: ignore - has_pyme = True - except ImportError: - has_pyme = False - -def _make_datetime(value) -> datetime: +def _make_datetime(value: int | float | str | datetime | date) -> datetime: if isinstance(value, (int, float)): # Timestamp value = datetime.fromtimestamp(value) @@ -59,7 +45,7 @@ def _make_datetime(value) -> datetime: # faster value = datetime.fromisoformat(value) except Exception: - value = parse(value) + value = parse(value) # type: ignore[arg-type] elif isinstance(value, datetime): pass elif isinstance(value, date): # NOTE: date has to be *after* datetime, or it will be overwritten @@ -73,7 +59,7 @@ def _make_datetime(value) -> datetime: return value -def make_bool(value: bool | int | str | dict | list | None) -> bool: +def make_bool(value: bool | int | str | dict[str, Any] | list[Any] | None) -> bool: """Converts the supplied value to a boolean. :param value: Value to interpret as a boolean. An empty string, dict @@ -96,14 +82,14 @@ def make_bool(value: bool | int | str | dict | list | None) -> bool: class MISPOrganisation(AbstractMISP): - _fields_for_feed: set = {'name', 'uuid'} + _fields_for_feed: set[str] = {'name', 'uuid'} def __init__(self) -> None: super().__init__() self.id: int self.name: str - def from_dict(self, **kwargs): + def from_dict(self, **kwargs) -> None: # type: ignore[no-untyped-def] if 'Organisation' in kwargs: kwargs = kwargs['Organisation'] super().from_dict(**kwargs) @@ -115,14 +101,14 @@ class MISPOrganisation(AbstractMISP): class MISPSharingGroupOrg(AbstractMISP): - _fields_for_feed: set = {'extend', 'Organisation'} + _fields_for_feed: set[str] = {'extend', 'Organisation'} def __init__(self) -> None: super().__init__() self.extend: bool self.Organisation: MISPOrganisation - def from_dict(self, **kwargs): + def from_dict(self, **kwargs) -> None: # type: ignore[no-untyped-def] if 'SharingGroupOrg' in kwargs: kwargs = kwargs['SharingGroupOrg'] if 'Organisation' in kwargs: @@ -135,14 +121,14 @@ class MISPSharingGroupOrg(AbstractMISP): return f'<{self.__class__.__name__}(Org={self.Organisation.name}, extend={self.extend})' return f'<{self.__class__.__name__}(NotInitialized)' - def _to_feed(self) -> dict: + def _to_feed(self) -> dict[str, Any]: to_return = super()._to_feed() to_return['Organisation'] = self.Organisation._to_feed() return to_return class MISPSharingGroup(AbstractMISP): - _fields_for_feed: set = {'uuid', 'name', 'roaming', 'created', 'organisation_uuid', 'Organisation', 'SharingGroupOrg', 'SharingGroupServer'} + _fields_for_feed: set[str] = {'uuid', 'name', 'roaming', 'created', 'organisation_uuid', 'Organisation', 'SharingGroupOrg', 'SharingGroupServer'} def __init__(self) -> None: super().__init__() @@ -154,19 +140,19 @@ class MISPSharingGroup(AbstractMISP): return self.SharingGroupOrg @sgorgs.setter - def sgorgs(self, sgorgs: list[MISPSharingGroupOrg]): + def sgorgs(self, sgorgs: list[MISPSharingGroupOrg]) -> None: if all(isinstance(x, MISPSharingGroupOrg) for x in sgorgs): self.SharingGroupOrg = sgorgs else: raise PyMISPError('All the attributes have to be of type MISPSharingGroupOrg.') - def add_sgorg(self, sgorg): + def add_sgorg(self, sgorg: dict[str, Any]) -> MISPSharingGroupOrg: misp_sgorg = MISPSharingGroupOrg() misp_sgorg.from_dict(**sgorg) self.SharingGroupOrg.append(misp_sgorg) return misp_sgorg - def from_dict(self, **kwargs): + def from_dict(self, **kwargs) -> None: # type: ignore[no-untyped-def] if 'SharingGroupOrg' in kwargs: [self.add_sgorg(sgorg) for sgorg in kwargs.pop('SharingGroupOrg')] if 'SharingGroup' in kwargs: @@ -178,7 +164,7 @@ class MISPSharingGroup(AbstractMISP): return f'<{self.__class__.__name__}(name={self.name})>' return f'<{self.__class__.__name__}(NotInitialized)>' - def _to_feed(self) -> dict: + def _to_feed(self) -> dict[str, Any]: to_return = super()._to_feed() to_return['SharingGroupOrg'] = [sgorg._to_feed() for sgorg in self.SharingGroupOrg] to_return['Organisation'].pop('id', None) @@ -197,7 +183,7 @@ class MISPShadowAttribute(AbstractMISP): self.type: str self.value: str - def from_dict(self, **kwargs): + def from_dict(self, **kwargs) -> None: # type: ignore[no-untyped-def] if 'ShadowAttribute' in kwargs: kwargs = kwargs['ShadowAttribute'] super().from_dict(**kwargs) @@ -215,7 +201,7 @@ class MISPSighting(AbstractMISP): self.id: int self.value: str - def from_dict(self, **kwargs): + def from_dict(self, **kwargs) -> None: # type: ignore[no-untyped-def] """Initialize the MISPSighting from a dictionary :param value: Value of the attribute the sighting is related too. Pushing this object @@ -241,11 +227,11 @@ class MISPSighting(AbstractMISP): class MISPAttribute(AbstractMISP): - _fields_for_feed: set = {'uuid', 'value', 'category', 'type', 'comment', 'data', - 'deleted', 'timestamp', 'to_ids', 'disable_correlation', - 'first_seen', 'last_seen'} + _fields_for_feed: set[str] = {'uuid', 'value', 'category', 'type', 'comment', 'data', + 'deleted', 'timestamp', 'to_ids', 'disable_correlation', + 'first_seen', 'last_seen'} - def __init__(self, describe_types: dict | None = None, strict: bool = False): + def __init__(self, describe_types: dict[str, Any] | None = None, strict: bool = False): """Represents an Attribute :param describe_types: Use it if you want to overwrite the default describeTypes.json file (you don't) @@ -268,6 +254,9 @@ class MISPAttribute(AbstractMISP): self.Tag: list[MISPTag] = [] self.Galaxy: list[MISPGalaxy] = [] + self.expand: str + self.timestamp: float | int | datetime + # For search self.Event: MISPEvent self.RelatedAttribute: list[MISPAttribute] @@ -275,7 +264,7 @@ class MISPAttribute(AbstractMISP): # For malware sample self._malware_binary: BytesIO | None - def add_tag(self, tag: str | MISPTag | dict | None = None, **kwargs) -> MISPTag: + def add_tag(self, tag: str | MISPTag | dict[str, Any] | None = None, **kwargs) -> MISPTag: # type: ignore[no-untyped-def] return super()._add_tag(tag, **kwargs) @property @@ -284,11 +273,11 @@ class MISPAttribute(AbstractMISP): return self.Tag @tags.setter - def tags(self, tags: list[MISPTag]): + def tags(self, tags: list[MISPTag]) -> None: """Set a list of prepared MISPTag.""" super()._set_tags(tags) - def add_galaxy(self, galaxy: MISPGalaxy | dict | None = None, **kwargs) -> MISPGalaxy: + def add_galaxy(self, galaxy: MISPGalaxy | dict[str, Any] | None = None, **kwargs) -> MISPGalaxy: # type: ignore[no-untyped-def] """Add a galaxy to the Attribute, either by passing a MISPGalaxy or a dictionary""" if isinstance(galaxy, MISPGalaxy): self.galaxies.append(galaxy) @@ -309,7 +298,7 @@ class MISPAttribute(AbstractMISP): """Returns a list of galaxies associated to this Attribute""" return self.Galaxy - def _prepare_data(self, data: Path | str | bytes | BytesIO | None): + def _prepare_data(self, data: Path | str | bytes | BytesIO | None) -> None: if not data: super().__setattr__('data', None) return @@ -341,7 +330,7 @@ class MISPAttribute(AbstractMISP): # not a encrypted zip file, assuming it is a new malware sample self._prepare_new_malware_sample() - def __setattr__(self, name: str, value: Any): + def __setattr__(self, name: str, value: Any) -> None: if name in ['first_seen', 'last_seen']: _datetime = _make_datetime(value) @@ -376,13 +365,13 @@ class MISPAttribute(AbstractMISP): h.update(to_encode.encode("utf-8")) return [h.hexdigest()] - def _set_default(self): + def _set_default(self) -> None: if not hasattr(self, 'comment'): self.comment = '' if not hasattr(self, 'timestamp'): self.timestamp = datetime.timestamp(datetime.now()) - def _to_feed(self, with_distribution=False) -> dict: + def _to_feed(self, with_distribution: bool=False) -> dict[str, Any]: if with_distribution: self._fields_for_feed.add('distribution') to_return = super()._to_feed() @@ -429,7 +418,7 @@ class MISPAttribute(AbstractMISP): return self.ShadowAttribute @shadow_attributes.setter - def shadow_attributes(self, shadow_attributes: list[MISPShadowAttribute]): + def shadow_attributes(self, shadow_attributes: list[MISPShadowAttribute]) -> None: """Set a list of prepared MISPShadowAttribute.""" if all(isinstance(x, MISPShadowAttribute) for x in shadow_attributes): self.ShadowAttribute = shadow_attributes @@ -441,22 +430,22 @@ class MISPAttribute(AbstractMISP): return self.Sighting @sightings.setter - def sightings(self, sightings: list[MISPSighting]): + def sightings(self, sightings: list[MISPSighting]) -> None: """Set a list of prepared MISPSighting.""" if all(isinstance(x, MISPSighting) for x in sightings): self.Sighting = sightings else: raise PyMISPError('All the attributes have to be of type MISPSighting.') - def delete(self): + def delete(self) -> None: """Mark the attribute as deleted (soft delete)""" self.deleted = True - def add_proposal(self, shadow_attribute=None, **kwargs) -> MISPShadowAttribute: + def add_proposal(self, shadow_attribute=None, **kwargs) -> MISPShadowAttribute: # type: ignore[no-untyped-def] """Alias for add_shadow_attribute""" return self.add_shadow_attribute(shadow_attribute, **kwargs) - def add_shadow_attribute(self, shadow_attribute: MISPShadowAttribute | dict | None = None, **kwargs) -> MISPShadowAttribute: + def add_shadow_attribute(self, shadow_attribute: MISPShadowAttribute | dict[str, Any] | None = None, **kwargs) -> MISPShadowAttribute: # type: ignore[no-untyped-def] """Add a shadow attribute to the attribute (by name or a MISPShadowAttribute object)""" if isinstance(shadow_attribute, MISPShadowAttribute): misp_shadow_attribute = shadow_attribute @@ -467,12 +456,12 @@ class MISPAttribute(AbstractMISP): misp_shadow_attribute = MISPShadowAttribute() misp_shadow_attribute.from_dict(**kwargs) else: - raise PyMISPError(f"The shadow_attribute is in an invalid format (can be either string, MISPShadowAttribute, or an expanded dict): {shadow_attribute}") + raise PyMISPError(f"The shadow_attribute is in an invalid format (can be either string, MISPShadowAttribute, or an expanded dict[str, Any]): {shadow_attribute}") self.shadow_attributes.append(misp_shadow_attribute) self.edited = True return misp_shadow_attribute - def add_sighting(self, sighting: MISPSighting | dict | None = None, **kwargs) -> MISPSighting: + def add_sighting(self, sighting: MISPSighting | dict[str, Any] | None = None, **kwargs) -> MISPSighting: # type: ignore[no-untyped-def] """Add a sighting to the attribute (by name or a MISPSighting object)""" if isinstance(sighting, MISPSighting): misp_sighting = sighting @@ -483,12 +472,12 @@ class MISPAttribute(AbstractMISP): misp_sighting = MISPSighting() misp_sighting.from_dict(**kwargs) else: - raise PyMISPError(f"The sighting is in an invalid format (can be either string, MISPShadowAttribute, or an expanded dict): {sighting}") + raise PyMISPError(f"The sighting is in an invalid format (can be either string, MISPShadowAttribute, or an expanded dict[str, Any]): {sighting}") self.sightings.append(misp_sighting) self.edited = True return misp_sighting - def from_dict(self, **kwargs): + def from_dict(self, **kwargs) -> None: # type: ignore[no-untyped-def] if 'Attribute' in kwargs: kwargs = kwargs['Attribute'] if kwargs.get('type') and kwargs.get('category'): @@ -610,13 +599,13 @@ class MISPAttribute(AbstractMISP): super().from_dict(**kwargs) - def to_dict(self, json_format: bool = False) -> dict: + def to_dict(self, json_format: bool = False) -> dict[str, Any]: to_return = super().to_dict(json_format) if self.data: to_return['data'] = base64.b64encode(self.data.getvalue()).decode() return to_return - def _prepare_new_malware_sample(self): + def _prepare_new_malware_sample(self) -> None: if '|' in self.value: # Get the filename, ignore the md5, because humans. self.malware_filename, md5 = self.value.rsplit('|', 1) @@ -627,7 +616,7 @@ class MISPAttribute(AbstractMISP): self._malware_binary = self.data self.encrypt = True - def __is_misp_encrypted_file(self, f) -> bool: + def __is_misp_encrypted_file(self, f: ZipFile) -> bool: files_list = f.namelist() if len(files_list) != 2: return False @@ -642,48 +631,16 @@ class MISPAttribute(AbstractMISP): return False return True - def __repr__(self): + def __repr__(self) -> str: if hasattr(self, 'value'): return '<{self.__class__.__name__}(type={self.type}, value={self.value})'.format(self=self) return f'<{self.__class__.__name__}(NotInitialized)' - def verify(self, gpg_uid): # pragma: no cover - # Not used - if not has_pyme: - raise PyMISPError('pyme is required, please install: pip install --pre pyme3. You will also need libgpg-error-dev and libgpgme11-dev.') - signed_data = self._serialize() - with gpg.Context() as c: - keys = list(c.keylist(gpg_uid)) - try: - c.verify(signed_data, signature=base64.b64decode(self.sig), verify=keys[:1]) - return {self.uuid: True} - except Exception: - return {self.uuid: False} - - def _serialize(self): # pragma: no cover - # Not used - return '{type}{category}{to_ids}{uuid}{timestamp}{comment}{deleted}{value}'.format( - type=self.type, category=self.category, to_ids=self.to_ids, uuid=self.uuid, timestamp=self.timestamp, - comment=self.comment, deleted=self.deleted, value=self.value).encode() - - def sign(self, gpg_uid, passphrase=None): # pragma: no cover - # Not used - if not has_pyme: - raise PyMISPError('pyme is required, please install: pip install --pre pyme3. You will also need libgpg-error-dev and libgpgme11-dev.') - to_sign = self._serialize() - with gpg.Context() as c: - keys = list(c.keylist(gpg_uid)) - c.signers = keys[:1] - if passphrase: - c.set_passphrase_cb(lambda *args: passphrase) - signed, _ = c.sign(to_sign, mode=mode.DETACH) - self.sig = base64.b64encode(signed).decode() - class MISPObjectReference(AbstractMISP): - _fields_for_feed: set = {'uuid', 'timestamp', 'relationship_type', 'comment', - 'object_uuid', 'referenced_uuid'} + _fields_for_feed: set[str] = {'uuid', 'timestamp', 'relationship_type', 'comment', + 'object_uuid', 'referenced_uuid'} def __init__(self) -> None: super().__init__() @@ -692,13 +649,13 @@ class MISPObjectReference(AbstractMISP): self.referenced_uuid: str self.relationship_type: str - def _set_default(self): + def _set_default(self) -> None: if not hasattr(self, 'comment'): self.comment = '' if not hasattr(self, 'timestamp'): self.timestamp = datetime.timestamp(datetime.now()) - def from_dict(self, **kwargs): + def from_dict(self, **kwargs) -> None: # type: ignore[no-untyped-def] if 'ObjectReference' in kwargs: kwargs = kwargs['ObjectReference'] super().from_dict(**kwargs) @@ -711,11 +668,12 @@ class MISPObjectReference(AbstractMISP): class MISPObject(AbstractMISP): - _fields_for_feed: set = {'name', 'meta-category', 'description', 'template_uuid', - 'template_version', 'uuid', 'timestamp', 'comment', - 'first_seen', 'last_seen', 'deleted'} + _fields_for_feed: set[str] = {'name', 'meta-category', 'description', 'template_uuid', + 'template_version', 'uuid', 'timestamp', 'comment', + 'first_seen', 'last_seen', 'deleted'} - def __init__(self, name: str, strict: bool = False, standalone: bool = True, default_attributes_parameters: dict = {}, **kwargs): + def __init__(self, name: str, strict: bool = False, standalone: bool = True, # type: ignore[no-untyped-def] + default_attributes_parameters: dict[str, Any] = {}, **kwargs) -> None: ''' Master class representing a generic MISP object :param name: Name of the object @@ -731,7 +689,8 @@ class MISPObject(AbstractMISP): self.name: str = name self._known_template: bool = False self.id: int - self._definition: dict | None + self._definition: dict[str, Any] | None + self.timestamp: float | int | datetime misp_objects_template_custom = kwargs.pop('misp_objects_template_custom', None) misp_objects_path_custom = kwargs.pop('misp_objects_path_custom', None) @@ -744,12 +703,12 @@ class MISPObject(AbstractMISP): self.uuid: str = str(uuid.uuid4()) self.first_seen: datetime self.last_seen: datetime - self.__fast_attribute_access: dict = defaultdict(list) # Hashtable object_relation: [attributes] + self.__fast_attribute_access: dict[str, Any] = defaultdict(list) # Hashtable object_relation: [attributes] self.ObjectReference: list[MISPObjectReference] = [] self._standalone: bool = False self.Attribute: list[MISPObjectAttribute] = [] self.SharingGroup: MISPSharingGroup - self._default_attributes_parameters: dict + self._default_attributes_parameters: dict[str, Any] if isinstance(default_attributes_parameters, MISPAttribute): # Just make sure we're not modifying an existing MISPAttribute self._default_attributes_parameters = default_attributes_parameters.to_dict() @@ -784,20 +743,20 @@ class MISPObject(AbstractMISP): self._load_template(template) return True - def _load_template(self, template: dict) -> None: + def _load_template(self, template: dict[str, Any]) -> None: self._definition = template setattr(self, 'meta-category', self._definition['meta-category']) self.template_uuid = self._definition['uuid'] self.description = self._definition['description'] self.template_version = self._definition['version'] - def _set_default(self): + def _set_default(self) -> None: if not hasattr(self, 'comment'): self.comment = '' if not hasattr(self, 'timestamp'): self.timestamp = datetime.timestamp(datetime.now()) - def _to_feed(self, with_distribution=False) -> dict: + def _to_feed(self, with_distribution: bool=False) -> dict[str, Any]: if with_distribution: self._fields_for_feed.add('distribution') if not hasattr(self, 'template_uuid'): # workaround for old events where the template_uuid was not yet mandatory @@ -816,7 +775,7 @@ class MISPObject(AbstractMISP): pass return to_return - def __setattr__(self, name, value): + def __setattr__(self, name: str, value: Any) -> None: if name in ['first_seen', 'last_seen']: value = _make_datetime(value) @@ -826,12 +785,12 @@ class MISPObject(AbstractMISP): logger.warning(f'first_seen ({value}) has to be before last_seen ({self.last_seen})') super().__setattr__(name, value) - def force_misp_objects_path_custom(self, misp_objects_path_custom: Path | str, object_name: str | None = None): + def force_misp_objects_path_custom(self, misp_objects_path_custom: Path | str, object_name: str | None = None) -> None: if object_name: self.name = object_name self._set_template(misp_objects_path_custom) - def _set_template(self, misp_objects_path_custom: Path | str | None = None, misp_objects_template_custom: dict | None = None): + def _set_template(self, misp_objects_path_custom: Path | str | None = None, misp_objects_template_custom: dict[str, Any] | None = None) -> None: if misp_objects_template_custom: # A complete template was given to the constructor self._load_template(misp_objects_template_custom) @@ -853,13 +812,14 @@ class MISPObject(AbstractMISP): # Then we have no meta-category, template_uuid, description and template_version pass - def delete(self): + def delete(self) -> None: """Mark the object as deleted (soft delete)""" self.deleted = True - [a.delete() for a in self.attributes] + for a in self.attributes: + a.delete() @property - def disable_validation(self): + def disable_validation(self) -> None: self._strict = False @property @@ -867,7 +827,7 @@ class MISPObject(AbstractMISP): return self.Attribute @attributes.setter - def attributes(self, attributes: list[MISPObjectAttribute]): + def attributes(self, attributes: list[MISPObjectAttribute]) -> None: if all(isinstance(x, MISPObjectAttribute) for x in attributes): self.Attribute = attributes self.__fast_attribute_access = defaultdict(list) @@ -879,18 +839,18 @@ class MISPObject(AbstractMISP): return self.ObjectReference @references.setter - def references(self, references: list[MISPObjectReference]): + def references(self, references: list[MISPObjectReference]) -> None: if all(isinstance(x, MISPObjectReference) for x in references): self.ObjectReference = references else: raise PyMISPError('All the attributes have to be of type MISPObjectReference.') @property - def standalone(self): + def standalone(self) -> bool: return self._standalone @standalone.setter - def standalone(self, new_standalone: bool): + def standalone(self, new_standalone: bool) -> None: if self._standalone != new_standalone: if new_standalone: self.update_not_jsonable("ObjectReference") @@ -900,7 +860,7 @@ class MISPObject(AbstractMISP): else: pass - def from_dict(self, **kwargs): + def from_dict(self, **kwargs) -> None: # type: ignore[no-untyped-def] if 'Object' in kwargs: kwargs = kwargs['Object'] if self._known_template: @@ -965,7 +925,7 @@ class MISPObject(AbstractMISP): super().from_dict(**kwargs) - def add_reference(self, referenced_uuid: AbstractMISP | str, relationship_type: str, comment: str | None = None, **kwargs) -> MISPObjectReference: + def add_reference(self, referenced_uuid: AbstractMISP | str, relationship_type: str, comment: str | None = None, **kwargs) -> MISPObjectReference: # type: ignore[no-untyped-def] """Add a link (uuid) to another object""" if isinstance(referenced_uuid, AbstractMISP): # Allow to pass an object or an attribute instead of its UUID @@ -992,7 +952,7 @@ class MISPObject(AbstractMISP): return self._fast_attribute_access.get(object_relation, []) @property - def _fast_attribute_access(self) -> dict: + def _fast_attribute_access(self) -> dict[str, Any]: if not self.__fast_attribute_access: for a in self.attributes: self.__fast_attribute_access[a.object_relation].append(a) @@ -1002,7 +962,7 @@ class MISPObject(AbstractMISP): '''True if all the relations in the list are defined in the object''' return all(relation in self._fast_attribute_access for relation in list_of_relations) - def add_attribute(self, object_relation: str, simple_value: str | int | float | None = None, **value) -> MISPAttribute | None: + def add_attribute(self, object_relation: str, simple_value: str | int | float | None = None, **value) -> MISPAttribute | None: # type: ignore[no-untyped-def] """Add an attribute. :param object_relation: The object relation of the attribute you're adding to the object :param simple_value: The value @@ -1050,7 +1010,7 @@ class MISPObject(AbstractMISP): self.edited = True return attribute - def add_attributes(self, object_relation: str, *attributes) -> list[MISPAttribute | None]: + def add_attributes(self, object_relation: str, *attributes: list[dict[str, Any] | MISPAttribute]) -> list[MISPAttribute | None]: '''Add multiple attributes with the same object_relation. Helper for object_relation when multiple is True in the template. It is the same as calling multiple times add_attribute with the same object_relation. @@ -1064,7 +1024,7 @@ class MISPObject(AbstractMISP): to_return.append(a) return to_return - def to_dict(self, json_format: bool = False, strict: bool = False) -> dict: + def to_dict(self, json_format: bool = False, strict: bool = False) -> dict[str, Any]: if strict or self._strict and self._known_template: self._validate() return super().to_dict(json_format) @@ -1103,9 +1063,11 @@ class MISPObject(AbstractMISP): class MISPEventReport(AbstractMISP): - _fields_for_feed: set = {'uuid', 'name', 'content', 'timestamp', 'deleted'} + _fields_for_feed: set[str] = {'uuid', 'name', 'content', 'timestamp', 'deleted'} - def from_dict(self, **kwargs): + timestamp: float | int | datetime + + def from_dict(self, **kwargs) -> None: # type: ignore[no-untyped-def] if 'EventReport' in kwargs: kwargs = kwargs['EventReport'] @@ -1154,7 +1116,7 @@ class MISPEventReport(AbstractMISP): return '<{self.__class__.__name__}(name={self.name})'.format(self=self) return f'<{self.__class__.__name__}(NotInitialized)' - def _set_default(self): + def _set_default(self) -> None: if not hasattr(self, 'timestamp'): self.timestamp = datetime.timestamp(datetime.now()) if not hasattr(self, 'name'): @@ -1182,13 +1144,13 @@ class MISPGalaxyClusterElement(AbstractMISP): return '<{self.__class__.__name__}(key={self.key}, value={self.value})'.format(self=self) return f'<{self.__class__.__name__}(NotInitialized)' - def __setattr__(self, key, value): + def __setattr__(self, key: str, value: Any) -> None: if key == "value" and isinstance(value, list): raise PyMISPError("You tried to set a list to a cluster element's value. " "Instead, create seperate elements for each value") super().__setattr__(key, value) - def from_dict(self, **kwargs): + def from_dict(self, **kwargs) -> None: # type: ignore[no-untyped-def] if kwargs.get('id'): self.id = int(kwargs.pop('id')) if kwargs.get('galaxy_cluster_id'): @@ -1222,7 +1184,7 @@ class MISPGalaxyClusterRelation(AbstractMISP): self.referenced_galaxy_cluster_type: str self.Tag: list[MISPTag] = [] - def from_dict(self, **kwargs): + def from_dict(self, **kwargs) -> None: # type: ignore[no-untyped-def] # Default values for a valid event to send to a MISP instance self.distribution = int(kwargs.pop('distribution', 0)) if self.distribution not in [0, 1, 2, 3, 4, 5]: @@ -1258,7 +1220,7 @@ class MISPGalaxyClusterRelation(AbstractMISP): self.SharingGroup.from_dict(**kwargs.pop('SharingGroup')) super().from_dict(**kwargs) - def add_tag(self, tag: str | MISPTag | dict | None = None, **kwargs) -> MISPTag: + def add_tag(self, tag: str | MISPTag | dict[str, Any] | None = None, **kwargs) -> MISPTag: # type: ignore[no-untyped-def] return super()._add_tag(tag, **kwargs) @property @@ -1267,7 +1229,7 @@ class MISPGalaxyClusterRelation(AbstractMISP): return self.Tag @tags.setter - def tags(self, tags: list[MISPTag]): + def tags(self, tags: list[MISPTag]) -> None: """Set a list of prepared MISPTag.""" super()._set_tags(tags) @@ -1298,7 +1260,7 @@ class MISPGalaxyCluster(AbstractMISP): super().__init__() self.Galaxy: MISPGalaxy self.GalaxyElement: list[MISPGalaxyClusterElement] = [] - self.meta: dict = {} + self.meta: dict[str, Any] = {} self.GalaxyClusterRelation: list[MISPGalaxyClusterRelation] = [] self.Org: MISPOrganisation self.Orgc: MISPOrganisation @@ -1312,7 +1274,7 @@ class MISPGalaxyCluster(AbstractMISP): return self.GalaxyElement @cluster_elements.setter - def cluster_elements(self, cluster_elements: list[MISPGalaxyClusterElement]): + def cluster_elements(self, cluster_elements: list[MISPGalaxyClusterElement]) -> None: self.GalaxyElement = cluster_elements @property @@ -1320,10 +1282,10 @@ class MISPGalaxyCluster(AbstractMISP): return self.GalaxyClusterRelation @cluster_relations.setter - def cluster_relations(self, cluster_relations: list[MISPGalaxyClusterRelation]): + def cluster_relations(self, cluster_relations: list[MISPGalaxyClusterRelation]) -> None: self.GalaxyClusterRelation = cluster_relations - def parse_meta_as_elements(self): + def parse_meta_as_elements(self) -> None: """Function to parse the meta field into GalaxyClusterElements""" # Parse the cluster elements from the kwargs meta fields for key, value in self.meta.items(): @@ -1334,7 +1296,7 @@ class MISPGalaxyCluster(AbstractMISP): self.add_cluster_element(key=key, value=v) @property - def elements_meta(self) -> dict: + def elements_meta(self) -> dict[str, Any]: """Function to return the galaxy cluster elements as a dictionary structure of lists that comes from a MISPGalaxy within a MISPEvent. Lossy, you lose the element ID """ @@ -1343,7 +1305,7 @@ class MISPGalaxyCluster(AbstractMISP): response[element.key].append(element.value) return dict(response) - def from_dict(self, **kwargs): + def from_dict(self, **kwargs) -> None: # type: ignore[no-untyped-def] if 'GalaxyCluster' in kwargs: kwargs = kwargs['GalaxyCluster'] self.default = kwargs.pop('default', False) @@ -1393,7 +1355,7 @@ class MISPGalaxyCluster(AbstractMISP): self.SharingGroup.from_dict(**kwargs.pop('SharingGroup')) super().from_dict(**kwargs) - def add_cluster_element(self, key: str, value: str, **kwargs) -> MISPGalaxyClusterElement: + def add_cluster_element(self, key: str, value: str, **kwargs) -> MISPGalaxyClusterElement: # type: ignore[no-untyped-def] """Add a cluster relation to a MISPGalaxyCluster, key and value are required :param key: The key name of the element @@ -1407,7 +1369,7 @@ class MISPGalaxyCluster(AbstractMISP): self.cluster_elements.append(cluster_element) return cluster_element - def add_cluster_relation(self, referenced_galaxy_cluster_uuid: MISPGalaxyCluster | str | UUID, referenced_galaxy_cluster_type: str, galaxy_cluster_uuid: str | None = None, **kwargs: dict) -> MISPGalaxyClusterRelation: + def add_cluster_relation(self, referenced_galaxy_cluster_uuid: MISPGalaxyCluster | str | UUID, referenced_galaxy_cluster_type: str, galaxy_cluster_uuid: str | None = None, **kwargs: dict[str, Any]) -> MISPGalaxyClusterRelation: """Add a cluster relation to a MISPGalaxyCluster. :param referenced_galaxy_cluster_uuid: UUID of the related cluster @@ -1448,7 +1410,7 @@ class MISPGalaxy(AbstractMISP): self.GalaxyCluster: list[MISPGalaxyCluster] = [] self.name: str - def from_dict(self, **kwargs): + def from_dict(self, **kwargs) -> None: # type: ignore[no-untyped-def] """Galaxy could be in one of the following formats: {'Galaxy': {}, 'GalaxyCluster': []} {'Galaxy': {'GalaxyCluster': []}} @@ -1466,7 +1428,7 @@ class MISPGalaxy(AbstractMISP): def clusters(self) -> list[MISPGalaxyCluster]: return self.GalaxyCluster - def add_galaxy_cluster(self, **kwargs) -> MISPGalaxyCluster: + def add_galaxy_cluster(self, **kwargs) -> MISPGalaxyCluster: # type: ignore[no-untyped-def] """Add a MISP galaxy cluster into a MISPGalaxy. Supports all other parameters supported by MISPGalaxyCluster""" @@ -1483,10 +1445,10 @@ class MISPGalaxy(AbstractMISP): class MISPEvent(AbstractMISP): - _fields_for_feed: set = {'uuid', 'info', 'threat_level_id', 'analysis', 'timestamp', - 'publish_timestamp', 'published', 'date', 'extends_uuid'} + _fields_for_feed: set[str] = {'uuid', 'info', 'threat_level_id', 'analysis', 'timestamp', + 'publish_timestamp', 'published', 'date', 'extends_uuid'} - def __init__(self, describe_types: dict | None = None, strict_validation: bool = False, **kwargs): + def __init__(self, describe_types: dict[str, Any] | None = None, strict_validation: bool = False, **kwargs) -> None: # type: ignore[no-untyped-def] super().__init__(**kwargs) self.__schema_file = 'schema.json' if strict_validation else 'schema-lax.json' @@ -1505,7 +1467,10 @@ class MISPEvent(AbstractMISP): self.Tag: list[MISPTag] = [] self.Galaxy: list[MISPGalaxy] = [] - def add_tag(self, tag: str | MISPTag | dict | None = None, **kwargs) -> MISPTag: + self.publish_timestamp: float | int | datetime + self.timestamp: float | int | datetime + + def add_tag(self, tag: str | MISPTag | dict[str, Any] | None = None, **kwargs) -> MISPTag: # type: ignore[no-untyped-def] return super()._add_tag(tag, **kwargs) @property @@ -1514,11 +1479,11 @@ class MISPEvent(AbstractMISP): return self.Tag @tags.setter - def tags(self, tags: list[MISPTag]): + def tags(self, tags: list[MISPTag]) -> None: """Set a list of prepared MISPTag.""" super()._set_tags(tags) - def _set_default(self): + def _set_default(self) -> None: """There are a few keys that could, or need to be set by default for the feed generator""" if not hasattr(self, 'published'): self.published = True @@ -1540,7 +1505,7 @@ class MISPEvent(AbstractMISP): self.threat_level_id = 4 @property - def manifest(self) -> dict: + def manifest(self) -> dict[str, Any]: required = ['info', 'Orgc'] for r in required: if not hasattr(self, r): @@ -1569,7 +1534,7 @@ class MISPEvent(AbstractMISP): to_return += attribute.hash_values(algorithm) return to_return - def to_feed(self, valid_distributions: list[int] = [0, 1, 2, 3, 4, 5], with_meta: bool = False, with_distribution=False, with_local_tags: bool = True, with_event_reports: bool = True) -> dict: + def to_feed(self, valid_distributions: list[int] = [0, 1, 2, 3, 4, 5], with_meta: bool = False, with_distribution: bool=False, with_local_tags: bool = True, with_event_reports: bool = True) -> dict[str, Any]: """ Generate a json output for MISP Feed. :param valid_distributions: only makes sense if the distribution key is set; i.e., the event is exported from a MISP instance. @@ -1655,7 +1620,7 @@ class MISPEvent(AbstractMISP): return self.Orgc @orgc.setter - def orgc(self, orgc: MISPOrganisation): + def orgc(self, orgc: MISPOrganisation) -> None: if isinstance(orgc, MISPOrganisation): self.Orgc = orgc else: @@ -1666,7 +1631,7 @@ class MISPEvent(AbstractMISP): return self.Attribute @attributes.setter - def attributes(self, attributes: list[MISPAttribute]): + def attributes(self, attributes: list[MISPAttribute]) -> None: if all(isinstance(x, MISPAttribute) for x in attributes): self.Attribute = attributes else: @@ -1681,7 +1646,7 @@ class MISPEvent(AbstractMISP): return self.ShadowAttribute @shadow_attributes.setter - def shadow_attributes(self, shadow_attributes: list[MISPShadowAttribute]): + def shadow_attributes(self, shadow_attributes: list[MISPShadowAttribute]) -> None: if all(isinstance(x, MISPShadowAttribute) for x in shadow_attributes): self.ShadowAttribute = shadow_attributes else: @@ -1696,7 +1661,7 @@ class MISPEvent(AbstractMISP): return self.Galaxy @galaxies.setter - def galaxies(self, galaxies: list[MISPGalaxy]): + def galaxies(self, galaxies: list[MISPGalaxy]) -> None: if all(isinstance(x, MISPGalaxy) for x in galaxies): self.Galaxy = galaxies else: @@ -1707,20 +1672,20 @@ class MISPEvent(AbstractMISP): return self.Object @objects.setter - def objects(self, objects: list[MISPObject]): + def objects(self, objects: list[MISPObject]) -> None: if all(isinstance(x, MISPObject) for x in objects): self.Object = objects else: raise PyMISPError('All the attributes have to be of type MISPObject.') - def load_file(self, event_path: Path | str, validate: bool = False, metadata_only: bool = False): + def load_file(self, event_path: Path | str, validate: bool = False, metadata_only: bool = False) -> None: """Load a JSON dump from a file on the disk""" if not os.path.exists(event_path): raise PyMISPError('Invalid path, unable to load the event.') with open(event_path, 'rb') as f: self.load(f, validate, metadata_only) - def load(self, json_event: IO | str | bytes | dict, validate: bool = False, metadata_only: bool = False): + def load(self, json_event: IO[bytes] | IO[str] | str | bytes | dict[str, Any], validate: bool = False, metadata_only: bool = False) -> None: """Load a JSON dump from a pseudo file or a JSON string""" if isinstance(json_event, (BufferedIOBase, TextIOBase)): json_event = json_event.read() @@ -1741,7 +1706,7 @@ class MISPEvent(AbstractMISP): if validate: warnings.warn('The validate parameter is deprecated because PyMISP is more flexible at loading event than the schema') - def __setattr__(self, name, value): + def __setattr__(self, name: str, value: Any) -> None: if name in ['date']: if isinstance(value, date): pass @@ -1759,7 +1724,7 @@ class MISPEvent(AbstractMISP): raise NewEventError(f'Invalid format for the date: {type(value)} - {value}') super().__setattr__(name, value) - def set_date(self, d: str | int | float | datetime | date | None = None, ignore_invalid: bool = False): + def set_date(self, d: str | int | float | datetime | date | None = None, ignore_invalid: bool = False) -> None: """Set a date for the event :param d: String, datetime, or date object @@ -1772,7 +1737,7 @@ class MISPEvent(AbstractMISP): else: raise NewEventError(f'Invalid format for the date: {type(d)} - {d}') - def from_dict(self, **kwargs): + def from_dict(self, **kwargs) -> None: # type: ignore[no-untyped-def] if 'Event' in kwargs: kwargs = kwargs['Event'] # Required value @@ -1831,7 +1796,7 @@ class MISPEvent(AbstractMISP): for rel_event in kwargs.pop('RelatedEvent'): sub_event = MISPEvent() sub_event.load(rel_event) - self.RelatedEvent.append({'Event': sub_event}) + self.RelatedEvent.append({'Event': sub_event}) # type: ignore[arg-type] if kwargs.get('Tag'): [self.add_tag(tag) for tag in kwargs.pop('Tag')] if kwargs.get('Object'): @@ -1848,7 +1813,7 @@ class MISPEvent(AbstractMISP): super().from_dict(**kwargs) - def to_dict(self, json_format: bool = False) -> dict: + def to_dict(self, json_format: bool = False) -> dict[str, Any]: to_return = super().to_dict(json_format) if to_return.get('date'): @@ -1862,11 +1827,11 @@ class MISPEvent(AbstractMISP): return to_return - def add_proposal(self, shadow_attribute=None, **kwargs) -> MISPShadowAttribute: + def add_proposal(self, shadow_attribute=None, **kwargs) -> MISPShadowAttribute: # type: ignore[no-untyped-def] """Alias for add_shadow_attribute""" return self.add_shadow_attribute(shadow_attribute, **kwargs) - def add_shadow_attribute(self, shadow_attribute=None, **kwargs) -> MISPShadowAttribute: + def add_shadow_attribute(self, shadow_attribute=None, **kwargs) -> MISPShadowAttribute: # type: ignore[no-untyped-def] """Add a tag to the attribute (by name or a MISPTag object)""" if isinstance(shadow_attribute, MISPShadowAttribute): misp_shadow_attribute = shadow_attribute @@ -1877,7 +1842,7 @@ class MISPEvent(AbstractMISP): misp_shadow_attribute = MISPShadowAttribute() misp_shadow_attribute.from_dict(**kwargs) else: - raise PyMISPError(f"The shadow_attribute is in an invalid format (can be either string, MISPShadowAttribute, or an expanded dict): {shadow_attribute}") + raise PyMISPError(f"The shadow_attribute is in an invalid format (can be either string, MISPShadowAttribute, or an expanded dict[str, Any]): {shadow_attribute}") self.shadow_attributes.append(misp_shadow_attribute) self.edited = True return misp_shadow_attribute @@ -1889,7 +1854,7 @@ class MISPEvent(AbstractMISP): """ tags: list[MISPTag] = [] for a in self.attributes + [attribute for o in self.objects for attribute in o.attributes]: - if ((hasattr(a, 'id') and a.id == attribute_identifier) + if ((hasattr(a, 'id') and str(a.id) == attribute_identifier) or (hasattr(a, 'uuid') and a.uuid == attribute_identifier) or (hasattr(a, 'value') and attribute_identifier == a.value or (isinstance(a.value, str) and attribute_identifier in a.value.split('|')))): @@ -1904,7 +1869,7 @@ class MISPEvent(AbstractMISP): """ attributes = [] for a in self.attributes + [attribute for o in self.objects for attribute in o.attributes]: - if ((hasattr(a, 'id') and a.id == attribute_identifier) + if ((hasattr(a, 'id') and str(a.id) == attribute_identifier) or (hasattr(a, 'uuid') and a.uuid == attribute_identifier) or (hasattr(a, 'value') and attribute_identifier == a.value or (isinstance(a.value, str) and attribute_identifier in a.value.split('|')))): @@ -1920,24 +1885,24 @@ class MISPEvent(AbstractMISP): """Mark the attribute as published""" self.published = True - def unpublish(self): + def unpublish(self) -> None: """Mark the attribute as un-published (set publish flag to false)""" self.published = False - def delete_attribute(self, attribute_id: str): + def delete_attribute(self, attribute_id: str) -> None: """Delete an attribute :param attribute_id: ID or UUID """ for a in self.attributes: - if ((hasattr(a, 'id') and a.id == attribute_id) + if ((hasattr(a, 'id') and str(a.id) == attribute_id) or (hasattr(a, 'uuid') and a.uuid == attribute_id)): a.delete() break else: raise PyMISPError(f'No attribute with UUID/ID {attribute_id} found.') - def add_attribute(self, type: str, value: str | int | float, **kwargs) -> MISPAttribute | list[MISPAttribute]: + def add_attribute(self, type: str, value: str | int | float, **kwargs) -> MISPAttribute | list[MISPAttribute]: # type: ignore[no-untyped-def] """Add an attribute. type and value are required but you can pass all other parameters supported by MISPAttribute""" attr_list: list[MISPAttribute] = [] @@ -1952,7 +1917,7 @@ class MISPEvent(AbstractMISP): return attr_list return attribute - def add_event_report(self, name: str, content: str, **kwargs) -> MISPEventReport: + def add_event_report(self, name: str, content: str, **kwargs) -> MISPEventReport: # type: ignore[no-untyped-def] """Add an event report. name and value are requred but you can pass all other parameters supported by MISPEventReport""" event_report = MISPEventReport() @@ -1961,7 +1926,7 @@ class MISPEvent(AbstractMISP): self.edited = True return event_report - def add_galaxy(self, galaxy: MISPGalaxy | dict | None = None, **kwargs) -> MISPGalaxy: + def add_galaxy(self, galaxy: MISPGalaxy | dict[str, Any] | None = None, **kwargs) -> MISPGalaxy: # type: ignore[no-untyped-def] """Add a galaxy and sub-clusters into an event, either by passing a MISPGalaxy or a dictionary. Supports all other parameters supported by MISPGalaxy""" @@ -2007,7 +1972,7 @@ class MISPEvent(AbstractMISP): objects.append(obj) return objects - def add_object(self, obj: MISPObject | dict | None = None, **kwargs) -> MISPObject: + def add_object(self, obj: MISPObject | dict[str, Any] | None = None, **kwargs) -> MISPObject: # type: ignore[no-untyped-def] """Add an object to the Event, either by passing a MISPObject, or a dictionary""" if isinstance(obj, MISPObject): misp_obj = obj @@ -2028,7 +1993,7 @@ class MISPEvent(AbstractMISP): self.edited = True return misp_obj - def delete_object(self, object_id: str): + def delete_object(self, object_id: str) -> None: """Delete an object :param object_id: ID or UUID @@ -2041,7 +2006,7 @@ class MISPEvent(AbstractMISP): else: raise PyMISPError(f'No object with UUID/ID {object_id} found.') - def run_expansions(self): + def run_expansions(self) -> None: for index, attribute in enumerate(self.attributes): if 'expand' not in attribute: continue @@ -2069,70 +2034,10 @@ class MISPEvent(AbstractMISP): return '<{self.__class__.__name__}(info={self.info})'.format(self=self) return f'<{self.__class__.__name__}(NotInitialized)' - def _serialize(self): # pragma: no cover - return '{date}{threat_level_id}{info}{uuid}{analysis}{timestamp}'.format( - date=self.date, threat_level_id=self.threat_level_id, info=self.info, - uuid=self.uuid, analysis=self.analysis, timestamp=self.timestamp).encode() - - def _serialize_sigs(self): # pragma: no cover - # Not used - all_sigs = self.sig - for a in self.attributes: - all_sigs += a.sig - return all_sigs.encode() - - def sign(self, gpg_uid, passphrase=None): # pragma: no cover - # Not used - if not has_pyme: - raise PyMISPError('pyme is required, please install: pip install --pre pyme3. You will also need libgpg-error-dev and libgpgme11-dev.') - to_sign = self._serialize() - with gpg.Context() as c: - keys = list(c.keylist(gpg_uid)) - c.signers = keys[:1] - if passphrase: - c.set_passphrase_cb(lambda *args: passphrase) - signed, _ = c.sign(to_sign, mode=mode.DETACH) - self.sig = base64.b64encode(signed).decode() - for a in self.attributes: - a.sign(gpg_uid, passphrase) - to_sign_global = self._serialize_sigs() - with gpg.Context() as c: - keys = list(c.keylist(gpg_uid)) - c.signers = keys[:1] - if passphrase: - c.set_passphrase_cb(lambda *args: passphrase) - signed, _ = c.sign(to_sign_global, mode=mode.DETACH) - self.global_sig = base64.b64encode(signed).decode() - - def verify(self, gpg_uid): # pragma: no cover - # Not used - if not has_pyme: - raise PyMISPError('pyme is required, please install: pip install --pre pyme3. You will also need libgpg-error-dev and libgpgme11-dev.') - to_return = {} - signed_data = self._serialize() - with gpg.Context() as c: - keys = list(c.keylist(gpg_uid)) - try: - c.verify(signed_data, signature=base64.b64decode(self.sig), verify=keys[:1]) - to_return[self.uuid] = True - except Exception: - to_return[self.uuid] = False - for a in self.attributes: - to_return.update(a.verify(gpg_uid)) - to_verify_global = self._serialize_sigs() - with gpg.Context() as c: - keys = list(c.keylist(gpg_uid)) - try: - c.verify(to_verify_global, signature=base64.b64decode(self.global_sig), verify=keys[:1]) - to_return['global'] = True - except Exception: - to_return['global'] = False - return to_return - class MISPObjectTemplate(AbstractMISP): - def from_dict(self, **kwargs): + def from_dict(self, **kwargs) -> None: # type: ignore[no-untyped-def] if 'ObjectTemplate' in kwargs: kwargs = kwargs['ObjectTemplate'] super().from_dict(**kwargs) @@ -2143,15 +2048,16 @@ class MISPObjectTemplate(AbstractMISP): class MISPUser(AbstractMISP): - def __init__(self, **kwargs: dict) -> None: + def __init__(self, **kwargs: dict[str, Any]) -> None: super().__init__(**kwargs) self.email: str + self.password: str | None - def from_dict(self, **kwargs): + def from_dict(self, **kwargs) -> None: # type: ignore[no-untyped-def] if 'User' in kwargs: kwargs = kwargs['User'] super().from_dict(**kwargs) - if hasattr(self, 'password') and set(self.password) == {'*'}: + if hasattr(self, 'password') and self.password and set(self.password) == {'*', }: self.password = None def __repr__(self) -> str: @@ -2162,7 +2068,9 @@ class MISPUser(AbstractMISP): class MISPFeed(AbstractMISP): - def from_dict(self, **kwargs): + settings: str + + def from_dict(self, **kwargs) -> None: # type: ignore[no-untyped-def] if 'Feed' in kwargs: kwargs = kwargs['Feed'] super().from_dict(**kwargs) @@ -2176,7 +2084,7 @@ class MISPFeed(AbstractMISP): class MISPWarninglist(AbstractMISP): - def from_dict(self, **kwargs): + def from_dict(self, **kwargs) -> None: # type: ignore[no-untyped-def] if 'Warninglist' in kwargs: kwargs = kwargs['Warninglist'] super().from_dict(**kwargs) @@ -2187,18 +2095,18 @@ class MISPTaxonomy(AbstractMISP): enabled: bool namespace: str - def from_dict(self, **kwargs): + def from_dict(self, **kwargs) -> None: # type: ignore[no-untyped-def] if 'Taxonomy' in kwargs: kwargs = kwargs['Taxonomy'] super().from_dict(**kwargs) - def __repr__(self): + def __repr__(self) -> str: return f'<{self.__class__.__name__}(namespace={self.namespace})>' class MISPNoticelist(AbstractMISP): - def from_dict(self, **kwargs): + def from_dict(self, **kwargs) -> None: # type: ignore[no-untyped-def] if 'Noticelist' in kwargs: kwargs = kwargs['Noticelist'] super().from_dict(**kwargs) @@ -2206,7 +2114,7 @@ class MISPNoticelist(AbstractMISP): class MISPCorrelationExclusion(AbstractMISP): - def from_dict(self, **kwargs): + def from_dict(self, **kwargs) -> None: # type: ignore[no-untyped-def] if 'CorrelationExclusion' in kwargs: kwargs = kwargs['CorrelationExclusion'] super().from_dict(**kwargs) @@ -2214,12 +2122,12 @@ class MISPCorrelationExclusion(AbstractMISP): class MISPRole(AbstractMISP): - def __init__(self, **kwargs: dict) -> None: + def __init__(self, **kwargs: dict[str, Any]) -> None: super().__init__(**kwargs) self.perm_admin: int self.perm_site_admin: int - def from_dict(self, **kwargs): + def from_dict(self, **kwargs) -> None: # type: ignore[no-untyped-def] if 'Role' in kwargs: kwargs = kwargs['Role'] super().from_dict(**kwargs) @@ -2227,7 +2135,7 @@ class MISPRole(AbstractMISP): class MISPServer(AbstractMISP): - def from_dict(self, **kwargs): + def from_dict(self, **kwargs) -> None: # type: ignore[no-untyped-def] if 'Server' in kwargs: kwargs = kwargs['Server'] super().from_dict(**kwargs) @@ -2235,13 +2143,13 @@ class MISPServer(AbstractMISP): class MISPLog(AbstractMISP): - def __init__(self, **kwargs: dict) -> None: + def __init__(self, **kwargs: dict[str, Any]) -> None: super().__init__(**kwargs) self.model: str self.action: str self.title: str - def from_dict(self, **kwargs): + def from_dict(self, **kwargs) -> None: # type: ignore[no-untyped-def] if 'Log' in kwargs: kwargs = kwargs['Log'] super().from_dict(**kwargs) @@ -2252,13 +2160,13 @@ class MISPLog(AbstractMISP): class MISPEventDelegation(AbstractMISP): - def __init__(self, **kwargs: dict) -> None: + def __init__(self, **kwargs: dict[str, Any]) -> None: super().__init__(**kwargs) self.org_id: int self.requester_org_id: int self.event_id: int - def from_dict(self, **kwargs): + def from_dict(self, **kwargs) -> None: # type: ignore[no-untyped-def] if 'EventDelegation' in kwargs: kwargs = kwargs['EventDelegation'] super().from_dict(**kwargs) @@ -2269,11 +2177,11 @@ class MISPEventDelegation(AbstractMISP): class MISPObjectAttribute(MISPAttribute): - _fields_for_feed: set = {'uuid', 'value', 'category', 'type', 'comment', 'data', - 'deleted', 'timestamp', 'to_ids', 'disable_correlation', - 'first_seen', 'last_seen', 'object_relation'} + _fields_for_feed: set[str] = {'uuid', 'value', 'category', 'type', 'comment', 'data', + 'deleted', 'timestamp', 'to_ids', 'disable_correlation', + 'first_seen', 'last_seen', 'object_relation'} - def __init__(self, definition): + def __init__(self, definition: dict[str, Any]) -> None: super().__init__() self._definition = definition @@ -2304,7 +2212,7 @@ class MISPObjectAttribute(MISPAttribute): raise NewAttributeError("The type of the attribute is required. Is the object template missing?") super().from_dict(**{**self, **kwargs}) - def __repr__(self): + def __repr__(self) -> str: if hasattr(self, 'value'): return '<{self.__class__.__name__}(object_relation={self.object_relation}, value={self.value})'.format(self=self) return f'<{self.__class__.__name__}(NotInitialized)' @@ -2312,82 +2220,91 @@ class MISPObjectAttribute(MISPAttribute): class MISPCommunity(AbstractMISP): - def from_dict(self, **kwargs): + def __init__(self, **kwargs: dict[str, Any]) -> None: + super().__init__(**kwargs) + self.name: str + + def from_dict(self, **kwargs) -> None: # type: ignore[no-untyped-def] if 'Community' in kwargs: kwargs = kwargs['Community'] super().from_dict(**kwargs) - def __repr__(self): + def __repr__(self) -> str: return f'<{self.__class__.__name__}(name={self.name}, uuid={self.uuid})' class MISPUserSetting(AbstractMISP): - def from_dict(self, **kwargs): + def __init__(self, **kwargs: dict[str, Any]) -> None: + super().__init__(**kwargs) + self.setting: str + + def from_dict(self, **kwargs) -> None: # type: ignore[no-untyped-def] if 'UserSetting' in kwargs: kwargs = kwargs['UserSetting'] super().from_dict(**kwargs) - def __repr__(self): + def __repr__(self) -> str: return f'<{self.__class__.__name__}(name={self.setting}' class MISPInbox(AbstractMISP): - def __init__(self, **kwargs: dict) -> None: + def __init__(self, **kwargs: dict[str, Any]) -> None: super().__init__(**kwargs) - self.data: dict + self.data: dict[str, Any] + self.type: str - def from_dict(self, **kwargs): + def from_dict(self, **kwargs) -> None: # type: ignore[no-untyped-def] if 'Inbox' in kwargs: kwargs = kwargs['Inbox'] super().from_dict(**kwargs) - def __repr__(self): + def __repr__(self) -> str: return f'<{self.__class__.__name__}(name={self.type})>' class MISPEventBlocklist(AbstractMISP): - def __init__(self, **kwargs: dict) -> None: + def __init__(self, **kwargs: dict[str, Any]) -> None: super().__init__(**kwargs) self.event_uuid: str - def from_dict(self, **kwargs): + def from_dict(self, **kwargs) -> None: # type: ignore[no-untyped-def] if 'EventBlocklist' in kwargs: kwargs = kwargs['EventBlocklist'] super().from_dict(**kwargs) - def __repr__(self): + def __repr__(self) -> str: return f'<{self.__class__.__name__}(event_uuid={self.event_uuid}' class MISPOrganisationBlocklist(AbstractMISP): - def __init__(self, **kwargs: dict) -> None: + def __init__(self, **kwargs: dict[str, Any]) -> None: super().__init__(**kwargs) self.org_uuid: str - def from_dict(self, **kwargs): + def from_dict(self, **kwargs) -> None: # type: ignore[no-untyped-def] if 'OrgBlocklist' in kwargs: kwargs = kwargs['OrgBlocklist'] super().from_dict(**kwargs) - def __repr__(self): + def __repr__(self) -> str: return f'<{self.__class__.__name__}(org_uuid={self.org_uuid}' class MISPDecayingModel(AbstractMISP): - def __init__(self, **kwargs: dict) -> None: + def __init__(self, **kwargs: dict[str, Any]) -> None: super().__init__(**kwargs) self.uuid: str self.id: int - def from_dict(self, **kwargs): + def from_dict(self, **kwargs) -> None: # type: ignore[no-untyped-def] if 'DecayingModel' in kwargs: kwargs = kwargs['DecayingModel'] super().from_dict(**kwargs) - def __repr__(self): + def __repr__(self) -> str: return f'<{self.__class__.__name__}(uuid={self.uuid})>' diff --git a/pymisp/tools/__init__.py b/pymisp/tools/__init__.py index 30ce253..45907b3 100644 --- a/pymisp/tools/__init__.py +++ b/pymisp/tools/__init__.py @@ -43,3 +43,13 @@ try: except ImportError: # Requires lief, optional [fileobjects] pass + +__all__ = ['VTReportObject', 'Neo4j', 'FileObject', 'make_binary_objects', + 'AbstractMISPObjectGenerator', 'GenericObjectGenerator', + 'load_openioc', 'load_openioc_file', 'SBSignatureObject', + 'Fail2BanObject', 'DomainIPObject', 'ASNObject', 'GeolocationObject', + 'GitVulnFinderObject', 'VehicleObject', 'CSVLoader', + 'SSHAuthorizedKeysObject', 'feed_meta_generator', 'update_objects', + 'EMailObject', 'URLObject', 'PEObject', 'PESectionObject', 'ELFObject', + 'ELFSectionObject', 'MachOObject', 'MachOSectionObject' + ] diff --git a/pymisp/tools/abstractgenerator.py b/pymisp/tools/abstractgenerator.py index 6e4b51c..2703c46 100644 --- a/pymisp/tools/abstractgenerator.py +++ b/pymisp/tools/abstractgenerator.py @@ -6,7 +6,6 @@ from .. import MISPObject from ..exceptions import InvalidMISPObject from datetime import datetime, date from dateutil.parser import parse -from typing import Union, Optional class AbstractMISPObjectGenerator(MISPObject): diff --git a/pymisp/tools/asnobject.py b/pymisp/tools/asnobject.py index ef237a2..a51c0b3 100644 --- a/pymisp/tools/asnobject.py +++ b/pymisp/tools/asnobject.py @@ -2,15 +2,18 @@ from __future__ import annotations -from .abstractgenerator import AbstractMISPObjectGenerator import logging +from typing import Any + +from .abstractgenerator import AbstractMISPObjectGenerator + logger = logging.getLogger('pymisp') class ASNObject(AbstractMISPObjectGenerator): - def __init__(self, parameters: dict, strict: bool = True, **kwargs): + def __init__(self, parameters: dict[str, Any], strict: bool = True, **kwargs) -> None: super().__init__('asn', strict=strict, **kwargs) self._parameters = parameters self.generate_attributes() diff --git a/tests/testlive_sync.py b/tests/testlive_sync.py index bad65a2..8d0e820 100644 --- a/tests/testlive_sync.py +++ b/tests/testlive_sync.py @@ -3,7 +3,6 @@ from __future__ import annotations import time -import sys import unittest import subprocess @@ -12,7 +11,7 @@ import logging logging.disable(logging.CRITICAL) try: - from pymisp import ExpandedPyMISP, MISPOrganisation, MISPUser, MISPEvent, MISPObject, MISPSharingGroup, Distribution + from pymisp import PyMISP, MISPOrganisation, MISPUser, MISPEvent, MISPObject, MISPSharingGroup, Distribution except ImportError: raise @@ -70,7 +69,7 @@ fast_mode = True class MISPInstance(): def __init__(self, params): - self.initial_user_connector = ExpandedPyMISP(params['url'], params['key'], ssl=False, debug=False) + self.initial_user_connector = PyMISP(params['url'], params['key'], ssl=False, debug=False) # Git pull self.initial_user_connector.update_misp() # Set the default role (id 3 on the VM is normal user) @@ -98,7 +97,7 @@ class MISPInstance(): user.org_id = self.test_org.id user.role_id = 1 # Site admin self.test_site_admin = self.initial_user_connector.add_user(user) - self.site_admin_connector = ExpandedPyMISP(params['url'], self.test_site_admin.authkey, ssl=False, debug=False) + self.site_admin_connector = PyMISP(params['url'], self.test_site_admin.authkey, ssl=False, debug=False) self.site_admin_connector.toggle_global_pythonify() # Create org admin user = MISPUser() @@ -106,14 +105,14 @@ class MISPInstance(): user.org_id = self.test_org.id user.role_id = 2 # Org admin self.test_org_admin = self.site_admin_connector.add_user(user) - self.org_admin_connector = ExpandedPyMISP(params['url'], self.test_org_admin.authkey, ssl=False, debug=False) + self.org_admin_connector = PyMISP(params['url'], self.test_org_admin.authkey, ssl=False, debug=False) self.org_admin_connector.toggle_global_pythonify() # Create user user = MISPUser() user.email = params['email_user'] user.org_id = self.test_org.id self.test_usr = self.org_admin_connector.add_user(user) - self.user_connector = ExpandedPyMISP(params['url'], self.test_usr.authkey, ssl=False, debug=False) + self.user_connector = PyMISP(params['url'], self.test_usr.authkey, ssl=False, debug=False) self.user_connector.toggle_global_pythonify() # Setup external_baseurl @@ -138,7 +137,7 @@ class MISPInstance(): user.org_id = sync_org.id user.role_id = 5 # Org admin sync_user = self.site_admin_connector.add_user(user) - sync_user_connector = ExpandedPyMISP(self.site_admin_connector.root_url, sync_user.authkey, ssl=False, debug=False) + sync_user_connector = PyMISP(self.site_admin_connector.root_url, sync_user.authkey, ssl=False, debug=False) sync_server_config = sync_user_connector.get_sync_config(pythonify=True) self.sync.append((sync_org, sync_user, sync_server_config)) From f3e17b38dd2c160b6c169424b1015c9743d9a457 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Vinot?= Date: Tue, 30 Jan 2024 13:27:59 +0100 Subject: [PATCH 47/80] fix: Compatibility with python 3.8 --- pymisp/abstract.py | 2 +- tests/test_mispevent.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pymisp/abstract.py b/pymisp/abstract.py index ec17e0f..c4de2e9 100644 --- a/pymisp/abstract.py +++ b/pymisp/abstract.py @@ -92,7 +92,7 @@ class MISPEncode(JSONEncoder): return JSONEncoder.default(self, obj) -class AbstractMISP(MutableMapping[str, Any], MISPFileCache, metaclass=ABCMeta): +class AbstractMISP(MutableMapping, MISPFileCache, metaclass=ABCMeta): # type: ignore[type-arg] __resources_path = resources_path __misp_objects_path = misp_objects_path __describe_types = describe_types diff --git a/tests/test_mispevent.py b/tests/test_mispevent.py index b5b79e9..d0a3bbd 100644 --- a/tests/test_mispevent.py +++ b/tests/test_mispevent.py @@ -92,7 +92,7 @@ class TestMISPEvent(unittest.TestCase): self.assertEqual(self.mispevent.to_json(sort_keys=True, indent=2), json.dumps(ref_json, sort_keys=True, indent=2)) # Fake setting an attribute ID for testing self.mispevent.attributes[0].id = 42 - self.mispevent.delete_attribute(42) + self.mispevent.delete_attribute('42') with open('tests/mispevent_testfiles/attribute_del.json') as f: ref_json = json.load(f) self.assertEqual(self.mispevent.to_json(sort_keys=True, indent=2), json.dumps(ref_json, sort_keys=True, indent=2)) From a2309317d3f202e6fc224cb2260a272773166494 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Vinot?= Date: Tue, 30 Jan 2024 13:33:38 +0100 Subject: [PATCH 48/80] fix: Run mypy on what I want --- .github/workflows/pytest.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/pytest.yml b/.github/workflows/pytest.yml index f61ef93..7ee00e4 100644 --- a/.github/workflows/pytest.yml +++ b/.github/workflows/pytest.yml @@ -34,13 +34,12 @@ jobs: - name: Test with nosetests run: | poetry run pytest --cov=pymisp tests/test_*.py - poetry run mypy tests/testlive_comprehensive.py tests/test_mispevent.py tests/testlive_sync.py pymisp + poetry run mypy . - name: Test with nosetests with orjson run: | pip3 install orjson poetry run pytest --cov=pymisp tests/test_*.py - poetry run mypy tests/testlive_comprehensive.py tests/test_mispevent.py tests/testlive_sync.py pymisp - name: Upload coverage to Codecov uses: codecov/codecov-action@v3 From ec11c1ee0c1152821a992348fb6197e2c25b10c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Vinot?= Date: Tue, 30 Jan 2024 13:35:59 +0100 Subject: [PATCH 49/80] fix: Also skip docs from mypy. --- mypy.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mypy.ini b/mypy.ini index 0351d61..f00223e 100644 --- a/mypy.ini +++ b/mypy.ini @@ -3,7 +3,7 @@ strict = True warn_return_any = False show_error_context = True pretty = True -exclude = feed-generator|examples|pymisp/tools|pymisp/data|tests +exclude = feed-generator|examples|pymisp/tools|pymisp/data|tests|docs # Stuff to remove gradually # disallow_untyped_defs = False From ca0fb8dc99e09eaee817b6830433ce8e49432128 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Vinot?= Date: Wed, 31 Jan 2024 12:15:08 +0100 Subject: [PATCH 50/80] chg: Use typing info of lief --- pymisp/tools/create_misp_object.py | 15 ++-- pymisp/tools/elfobject.py | 46 ++++++++---- pymisp/tools/machoobject.py | 49 ++++++++---- pymisp/tools/peobject.py | 116 ++++++++++++++++++----------- 4 files changed, 146 insertions(+), 80 deletions(-) diff --git a/pymisp/tools/create_misp_object.py b/pymisp/tools/create_misp_object.py index 7c2a181..31e7048 100644 --- a/pymisp/tools/create_misp_object.py +++ b/pymisp/tools/create_misp_object.py @@ -2,12 +2,13 @@ from __future__ import annotations -from io import BytesIO - -from . import FileObject -from ..exceptions import MISPObjectException import logging +from io import BytesIO +from typing import Any + +from . import FileObject, PEObject, ELFObject, MachOObject, PESectionObject, ELFSectionObject, MachOSectionObject +from ..exceptions import MISPObjectException logger = logging.getLogger('pymisp') try: @@ -32,7 +33,11 @@ class FileTypeNotImplemented(MISPObjectException): pass -def make_binary_objects(filepath: str | None = None, pseudofile: BytesIO | bytes | None = None, filename: str | None = None, standalone: bool = True, default_attributes_parameters: dict = {}): +def make_binary_objects(filepath: str | None = None, + pseudofile: BytesIO | bytes | None = None, + filename: str | None = None, + standalone: bool = True, + default_attributes_parameters: dict[str, Any] = {}) -> tuple[FileObject, PEObject | ELFObject | MachOObject | None, list[PESectionObject] | list[ELFSectionObject] | list[MachOSectionObject]]: misp_file = FileObject(filepath=filepath, pseudofile=pseudofile, filename=filename, standalone=standalone, default_attributes_parameters=default_attributes_parameters) if HAS_LIEF and (filepath or pseudofile): diff --git a/pymisp/tools/elfobject.py b/pymisp/tools/elfobject.py index 80ad7c8..c0b6ceb 100644 --- a/pymisp/tools/elfobject.py +++ b/pymisp/tools/elfobject.py @@ -2,13 +2,16 @@ from __future__ import annotations +import logging + +from hashlib import md5, sha1, sha256, sha512 +from io import BytesIO +from pathlib import Path +from typing import Any + +from . import FileObject from .abstractgenerator import AbstractMISPObjectGenerator from ..exceptions import InvalidMISPObject -from io import BytesIO -from hashlib import md5, sha1, sha256, sha512 -import logging -from pathlib import Path -from . import FileObject import lief @@ -21,7 +24,10 @@ except ImportError: logger = logging.getLogger('pymisp') -def make_elf_objects(lief_parsed: lief.ELF.Binary, misp_file: FileObject, standalone: bool = True, default_attributes_parameters: dict = {}): +def make_elf_objects(lief_parsed: lief.ELF.Binary, + misp_file: FileObject, + standalone: bool = True, + default_attributes_parameters: dict[str, Any] = {}) -> tuple[FileObject, ELFObject, list[ELFSectionObject]]: elf_object = ELFObject(parsed=lief_parsed, standalone=standalone, default_attributes_parameters=default_attributes_parameters) misp_file.add_reference(elf_object.uuid, 'includes', 'ELF indicators') elf_sections = [] @@ -32,22 +38,30 @@ def make_elf_objects(lief_parsed: lief.ELF.Binary, misp_file: FileObject, standa class ELFObject(AbstractMISPObjectGenerator): - def __init__(self, parsed: lief.ELF.Binary | None = None, filepath: Path | str | None = None, pseudofile: BytesIO | bytes | list[int] | None = None, **kwargs): + __elf: lief.ELF.Binary + + def __init__(self, parsed: lief.ELF.Binary | None = None, # type: ignore[no-untyped-def] + filepath: Path | str | None = None, + pseudofile: BytesIO | bytes | list[int] | None = None, **kwargs) -> None: """Creates an ELF object, with lief""" super().__init__('elf', **kwargs) if not HAS_PYDEEP: logger.warning("pydeep is missing, please install pymisp this way: pip install pymisp[fileobjects]") if pseudofile: if isinstance(pseudofile, BytesIO): - self.__elf = lief.ELF.parse(obj=pseudofile) + e = lief.ELF.parse(obj=pseudofile) elif isinstance(pseudofile, bytes): - self.__elf = lief.ELF.parse(raw=list(pseudofile)) + e = lief.ELF.parse(raw=list(pseudofile)) elif isinstance(pseudofile, list): - self.__elf = lief.ELF.parse(raw=pseudofile) + e = lief.ELF.parse(raw=pseudofile) else: raise InvalidMISPObject(f'Pseudo file can be BytesIO or bytes got {type(pseudofile)}') + if not e: + raise InvalidMISPObject('Unable to parse pseudofile') + self.__elf = e elif filepath: - self.__elf = lief.ELF.parse(filepath) + if e := lief.ELF.parse(filepath): + self.__elf = e elif parsed: # Got an already parsed blob if isinstance(parsed, lief.ELF.Binary): @@ -56,7 +70,7 @@ class ELFObject(AbstractMISPObjectGenerator): raise InvalidMISPObject(f'Not a lief.ELF.Binary: {type(parsed)}') self.generate_attributes() - def generate_attributes(self): + def generate_attributes(self) -> None: # General information self.add_attribute('type', value=str(self.__elf.header.file_type).split('.')[1]) self.add_attribute('entrypoint-address', value=self.__elf.entrypoint) @@ -78,7 +92,7 @@ class ELFObject(AbstractMISPObjectGenerator): class ELFSectionObject(AbstractMISPObjectGenerator): - def __init__(self, section: lief.ELF.Section, **kwargs): + def __init__(self, section: lief.ELF.Section, **kwargs) -> None: # type: ignore[no-untyped-def] """Creates an ELF Section object. Object generated by ELFObject.""" # Python3 way # super().__init__('pe-section') @@ -87,13 +101,13 @@ class ELFSectionObject(AbstractMISPObjectGenerator): self.__data = bytes(self.__section.content) self.generate_attributes() - def generate_attributes(self): + def generate_attributes(self) -> None: self.add_attribute('name', value=self.__section.name) self.add_attribute('type', value=str(self.__section.type).split('.')[1]) for flag in self.__section.flags_list: self.add_attribute('flag', value=str(flag).split('.')[1]) - size = self.add_attribute('size-in-bytes', value=self.__section.size) - if int(size.value) > 0: + self.add_attribute('size-in-bytes', value=self.__section.size) + if int(self.__section.size) > 0: self.add_attribute('entropy', value=self.__section.entropy) self.add_attribute('md5', value=md5(self.__data).hexdigest()) self.add_attribute('sha1', value=sha1(self.__data).hexdigest()) diff --git a/pymisp/tools/machoobject.py b/pymisp/tools/machoobject.py index 58f2e70..ad68e46 100644 --- a/pymisp/tools/machoobject.py +++ b/pymisp/tools/machoobject.py @@ -2,13 +2,17 @@ from __future__ import annotations -from ..exceptions import InvalidMISPObject -from .abstractgenerator import AbstractMISPObjectGenerator -from io import BytesIO -from hashlib import md5, sha1, sha256, sha512 import logging + +from hashlib import md5, sha1, sha256, sha512 +from io import BytesIO from pathlib import Path +from typing import Any + +from ..exceptions import InvalidMISPObject + from . import FileObject +from .abstractgenerator import AbstractMISPObjectGenerator import lief @@ -21,7 +25,10 @@ except ImportError: logger = logging.getLogger('pymisp') -def make_macho_objects(lief_parsed: lief.MachO.Binary, misp_file: FileObject, standalone: bool = True, default_attributes_parameters: dict = {}): +def make_macho_objects(lief_parsed: lief.MachO.Binary, + misp_file: FileObject, + standalone: bool = True, + default_attributes_parameters: dict[str, Any] = {}) -> tuple[FileObject, MachOObject, list[MachOSectionObject]]: macho_object = MachOObject(parsed=lief_parsed, standalone=standalone, default_attributes_parameters=default_attributes_parameters) misp_file.add_reference(macho_object.uuid, 'includes', 'MachO indicators') macho_sections = [] @@ -32,33 +39,43 @@ def make_macho_objects(lief_parsed: lief.MachO.Binary, misp_file: FileObject, st class MachOObject(AbstractMISPObjectGenerator): - def __init__(self, parsed: lief.MachO.Binary | None = None, filepath: Path | str | None = None, pseudofile: BytesIO | list[int] | None = None, **kwargs): + __macho: lief.MachO.Binary + + def __init__(self, parsed: lief.MachO.Binary | lief.MachO.FatBinary | None = None, # type: ignore[no-untyped-def] + filepath: Path | str | None = None, + pseudofile: BytesIO | list[int] | None = None, + **kwargs) -> None: """Creates an MachO object, with lief""" super().__init__('macho', **kwargs) if not HAS_PYDEEP: logger.warning("pydeep is missing, please install pymisp this way: pip install pymisp[fileobjects]") if pseudofile: if isinstance(pseudofile, BytesIO): - self.__macho = lief.MachO.parse(obj=pseudofile) + m = lief.MachO.parse(obj=pseudofile) elif isinstance(pseudofile, bytes): - self.__macho = lief.MachO.parse(raw=list(pseudofile)) + m = lief.MachO.parse(raw=list(pseudofile)) elif isinstance(pseudofile, list): - self.__macho = lief.MachO.parse(raw=pseudofile) + m = lief.MachO.parse(raw=pseudofile) else: raise InvalidMISPObject(f'Pseudo file can be BytesIO or bytes got {type(pseudofile)}') + if not m: + raise InvalidMISPObject('Unable to parse pseudofile') + self.__macho = m.at(0) elif filepath: - self.__macho = lief.MachO.parse(filepath) + if m := lief.MachO.parse(filepath): + self.__macho = m.at(0) elif parsed: # Got an already parsed blob if isinstance(parsed, lief.MachO.FatBinary): + self.__macho = parsed.at(0) + elif isinstance(parsed, lief.MachO.Binary): self.__macho = parsed else: raise InvalidMISPObject(f'Not a lief.MachO.Binary: {type(parsed)}') self.generate_attributes() - def generate_attributes(self): + def generate_attributes(self) -> None: self.add_attribute('type', value=str(self.__macho.header.file_type).split('.')[1]) - self.add_attribute('name', value=self.__macho.name) # General information if self.__macho.has_entrypoint: self.add_attribute('entrypoint-address', value=self.__macho.entrypoint) @@ -76,7 +93,7 @@ class MachOObject(AbstractMISPObjectGenerator): class MachOSectionObject(AbstractMISPObjectGenerator): - def __init__(self, section: lief.MachO.Section, **kwargs): + def __init__(self, section: lief.MachO.Section, **kwargs) -> None: # type: ignore[no-untyped-def] """Creates an MachO Section object. Object generated by MachOObject.""" # Python3 way # super().__init__('pe-section') @@ -85,10 +102,10 @@ class MachOSectionObject(AbstractMISPObjectGenerator): self.__data = bytes(self.__section.content) self.generate_attributes() - def generate_attributes(self): + def generate_attributes(self) -> None: self.add_attribute('name', value=self.__section.name) - size = self.add_attribute('size-in-bytes', value=self.__section.size) - if int(size.value) > 0: + self.add_attribute('size-in-bytes', value=self.__section.size) + if int(self.__section.size) > 0: self.add_attribute('entropy', value=self.__section.entropy) self.add_attribute('md5', value=md5(self.__data).hexdigest()) self.add_attribute('sha1', value=sha1(self.__data).hexdigest()) diff --git a/pymisp/tools/peobject.py b/pymisp/tools/peobject.py index 92b3ff8..e83bbb3 100644 --- a/pymisp/tools/peobject.py +++ b/pymisp/tools/peobject.py @@ -2,16 +2,18 @@ from __future__ import annotations -from ..exceptions import InvalidMISPObject -from .abstractgenerator import AbstractMISPObjectGenerator -from io import BytesIO -from hashlib import md5, sha1, sha256, sha512 -from datetime import datetime import logging -from pathlib import Path + from base64 import b64encode +from datetime import datetime +from hashlib import md5, sha1, sha256, sha512 +from io import BytesIO +from pathlib import Path +from typing import Any from . import FileObject +from .abstractgenerator import AbstractMISPObjectGenerator +from ..exceptions import InvalidMISPObject import lief @@ -24,7 +26,10 @@ except ImportError: logger = logging.getLogger('pymisp') -def make_pe_objects(lief_parsed: lief.PE.Binary, misp_file: FileObject, standalone: bool = True, default_attributes_parameters: dict = {}): +def make_pe_objects(lief_parsed: lief.PE.Binary, + misp_file: FileObject, + standalone: bool = True, + default_attributes_parameters: dict[str, Any] = {}) -> tuple[FileObject, PEObject, list[PESectionObject]]: pe_object = PEObject(parsed=lief_parsed, standalone=standalone, default_attributes_parameters=default_attributes_parameters) misp_file.add_reference(pe_object.uuid, 'includes', 'PE indicators') pe_sections = [] @@ -35,22 +40,33 @@ def make_pe_objects(lief_parsed: lief.PE.Binary, misp_file: FileObject, standalo class PEObject(AbstractMISPObjectGenerator): - def __init__(self, parsed: lief.PE.Binary | None = None, filepath: Path | str | None = None, pseudofile: BytesIO | list[int] | None = None, **kwargs): + __pe: lief.PE.Binary + + def __init__(self, parsed: lief.PE.Binary | None = None, # type: ignore[no-untyped-def] + filepath: Path | str | None = None, + pseudofile: BytesIO | list[int] | None = None, + **kwargs) -> None: """Creates an PE object, with lief""" super().__init__('pe', **kwargs) if not HAS_PYDEEP: logger.warning("pydeep is missing, please install pymisp this way: pip install pymisp[fileobjects]") if pseudofile: if isinstance(pseudofile, BytesIO): - self.__pe = lief.PE.parse(obj=pseudofile) + p = lief.PE.parse(obj=pseudofile) elif isinstance(pseudofile, bytes): - self.__pe = lief.PE.parse(raw=list(pseudofile)) + p = lief.PE.parse(raw=list(pseudofile)) elif isinstance(pseudofile, list): - self.__pe = lief.PE.parse(raw=pseudofile) + p = lief.PE.parse(raw=pseudofile) else: raise InvalidMISPObject(f'Pseudo file can be BytesIO or bytes got {type(pseudofile)}') + if not p: + raise InvalidMISPObject('Unable to parse pseudofile') + self.__pe = p elif filepath: - self.__pe = lief.PE.parse(filepath) + if p := lief.PE.parse(filepath): + self.__pe = p + else: + raise InvalidMISPObject(f'Unable to parse {filepath}') elif parsed: # Got an already parsed blob if isinstance(parsed, lief.PE.Binary): @@ -59,22 +75,22 @@ class PEObject(AbstractMISPObjectGenerator): raise InvalidMISPObject(f'Not a lief.PE.Binary: {type(parsed)}') self.generate_attributes() - def _is_exe(self): + def _is_exe(self) -> bool: if not self._is_dll() and not self._is_driver(): - return self.__pe.header.has_characteristic(lief.PE.HEADER_CHARACTERISTICS.EXECUTABLE_IMAGE) + return self.__pe.header.has_characteristic(lief.PE.Header.CHARACTERISTICS.EXECUTABLE_IMAGE) return False - def _is_dll(self): - return self.__pe.header.has_characteristic(lief.PE.HEADER_CHARACTERISTICS.DLL) + def _is_dll(self) -> bool: + return self.__pe.header.has_characteristic(lief.PE.Header.CHARACTERISTICS.DLL) - def _is_driver(self): + def _is_driver(self) -> bool: # List from pefile system_DLLs = {'ntoskrnl.exe', 'hal.dll', 'ndis.sys', 'bootvid.dll', 'kdcom.dll'} if system_DLLs.intersection([imp.lower() for imp in self.__pe.libraries]): return True return False - def _get_pe_type(self): + def _get_pe_type(self) -> str: if self._is_dll(): return 'dll' elif self._is_driver(): @@ -84,31 +100,27 @@ class PEObject(AbstractMISPObjectGenerator): else: return 'unknown' - def generate_attributes(self): + def generate_attributes(self) -> None: self.add_attribute('type', value=self._get_pe_type()) # General information self.add_attribute('entrypoint-address', value=self.__pe.entrypoint) self.add_attribute('compilation-timestamp', value=datetime.utcfromtimestamp(self.__pe.header.time_date_stamps).isoformat()) self.add_attribute('imphash', value=lief.PE.get_imphash(self.__pe, lief.PE.IMPHASH_MODE.PEFILE)) self.add_attribute('authentihash', value=self.__pe.authentihash_sha256.hex()) - try: - if (self.__pe.has_resources - and self.__pe.resources_manager.has_version - and self.__pe.resources_manager.version.has_string_file_info - and self.__pe.resources_manager.version.string_file_info.langcode_items): - fileinfo = dict(self.__pe.resources_manager.version.string_file_info.langcode_items[0].items.items()) + r_manager = self.__pe.resources_manager + if isinstance(r_manager, lief.PE.ResourcesManager): + version = r_manager.version + if isinstance(version, lief.PE.ResourceVersion) and version.string_file_info is not None: + fileinfo = dict(version.string_file_info.langcode_items[0].items.items()) self.add_attribute('original-filename', value=fileinfo.get('OriginalFilename')) self.add_attribute('internal-filename', value=fileinfo.get('InternalName')) self.add_attribute('file-description', value=fileinfo.get('FileDescription')) self.add_attribute('file-version', value=fileinfo.get('FileVersion')) - self.add_attribute('lang-id', value=self.__pe.resources_manager.version.string_file_info.langcode_items[0].key) self.add_attribute('product-name', value=fileinfo.get('ProductName')) self.add_attribute('product-version', value=fileinfo.get('ProductVersion')) self.add_attribute('company-name', value=fileinfo.get('CompanyName')) self.add_attribute('legal-copyright', value=fileinfo.get('LegalCopyright')) - except lief.read_out_of_bound: - # The file is corrupted - pass + self.add_attribute('lang-id', value=version.string_file_info.langcode_items[0].key) # Sections self.sections = [] if self.__pe.sections: @@ -121,7 +133,11 @@ class PEObject(AbstractMISPObjectGenerator): self.add_reference(s.uuid, 'includes', f'Section {pos} of PE') if ((self.__pe.entrypoint >= section.virtual_address) and (self.__pe.entrypoint < (section.virtual_address + section.virtual_size))): - self.add_attribute('entrypoint-section-at-position', value=f'{section.name}|{pos}') + if isinstance(section.name, bytes): + section_name = section.name.decode() + else: + section_name = section.name + self.add_attribute('entrypoint-section-at-position', value=f'{section_name}|{pos}') pos += 1 self.sections.append(s) self.add_attribute('number-sections', value=len(self.sections)) @@ -141,16 +157,30 @@ class PEObject(AbstractMISPObjectGenerator): class PECertificate(AbstractMISPObjectGenerator): - def __init__(self, certificate: lief.PE.x509, **kwargs): + def __init__(self, certificate: lief.PE.x509, **kwargs) -> None: # type: ignore[no-untyped-def] super().__init__('x509') self.__certificate = certificate self.generate_attributes() - def generate_attributes(self): + def generate_attributes(self) -> None: self.add_attribute('issuer', value=self.__certificate.issuer) self.add_attribute('serial-number', value=self.__certificate.serial_number) - self.add_attribute('validity-not-before', value=datetime(*self.__certificate.valid_from)) - self.add_attribute('validity-not-after', value=datetime(*self.__certificate.valid_to)) + if len(self.__certificate.valid_from) == 6: + self.add_attribute('validity-not-before', + value=datetime(year=self.__certificate.valid_from[0], + month=self.__certificate.valid_from[1], + day=self.__certificate.valid_from[2], + hour=self.__certificate.valid_from[3], + minute=self.__certificate.valid_from[4], + second=self.__certificate.valid_from[5])) + if len(self.__certificate.valid_to) == 6: + self.add_attribute('validity-not-after', + value=datetime(year=self.__certificate.valid_to[0], + month=self.__certificate.valid_to[1], + day=self.__certificate.valid_to[2], + hour=self.__certificate.valid_to[3], + minute=self.__certificate.valid_to[4], + second=self.__certificate.valid_to[5])) self.add_attribute('version', value=self.__certificate.version) self.add_attribute('subject', value=self.__certificate.subject) self.add_attribute('signature_algorithm', value=self.__certificate.signature_algorithm) @@ -159,19 +189,19 @@ class PECertificate(AbstractMISPObjectGenerator): class PESigners(AbstractMISPObjectGenerator): - def __init__(self, signer: lief.PE.SignerInfo, **kwargs): + def __init__(self, signer: lief.PE.SignerInfo, **kwargs) -> None: # type: ignore[no-untyped-def] super().__init__('authenticode-signerinfo') self.__signer = signer self.generate_attributes() - def generate_attributes(self): + def generate_attributes(self) -> None: self.add_attribute('issuer', value=self.__signer.issuer) self.add_attribute('serial-number', value=self.__signer.serial_number) self.add_attribute('version', value=self.__signer.version) - self.add_attribute('digest_algorithm', value=self.__signer.digest_algorithm.name) - self.add_attribute('encryption_algorithm', value=self.__signer.encryption_algorithm.name) + self.add_attribute('digest_algorithm', value=str(self.__signer.digest_algorithm)) + self.add_attribute('encryption_algorithm', value=str(self.__signer.encryption_algorithm)) self.add_attribute('digest-base64', value=b64encode(self.__signer.encrypted_digest)) - info = self.__signer.get_attribute(lief.PE.SIG_ATTRIBUTE_TYPES.SPC_SP_OPUS_INFO) + info: lief.PE.SpcSpOpusInfo = self.__signer.get_attribute(lief.PE.SIG_ATTRIBUTE_TYPES.SPC_SP_OPUS_INFO) # type: ignore[attr-defined, assignment] if info: self.add_attribute('program-name', value=info.program_name) self.add_attribute('url', value=info.more_info) @@ -179,17 +209,17 @@ class PESigners(AbstractMISPObjectGenerator): class PESectionObject(AbstractMISPObjectGenerator): - def __init__(self, section: lief.PE.Section, **kwargs): + def __init__(self, section: lief.PE.Section, **kwargs) -> None: # type: ignore[no-untyped-def] """Creates an PE Section object. Object generated by PEObject.""" super().__init__('pe-section') self.__section = section self.__data = bytes(self.__section.content) self.generate_attributes() - def generate_attributes(self): + def generate_attributes(self) -> None: self.add_attribute('name', value=self.__section.name) - size = self.add_attribute('size-in-bytes', value=self.__section.size) - if int(size.value) > 0: + self.add_attribute('size-in-bytes', value=self.__section.size) + if int(self.__section.size) > 0: # zero-filled sections can create too many correlations to_ids = float(self.__section.entropy) > 0 disable_correlation = not to_ids From 9853f23683cbdf86ec60f9f55cec17b50346ec98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Vinot?= Date: Wed, 31 Jan 2024 15:20:31 +0100 Subject: [PATCH 51/80] chg: Add a bunch more typing. --- pymisp/tools/abstractgenerator.py | 13 ++++--- pymisp/tools/asnobject.py | 4 +-- pymisp/tools/create_misp_object.py | 6 ++-- pymisp/tools/csvloader.py | 10 +++--- pymisp/tools/domainipobject.py | 9 +++-- pymisp/tools/emailobject.py | 58 +++++++++++++++++------------- pymisp/tools/genericgenerator.py | 5 +-- pymisp/tools/microblogobject.py | 25 ++++++------- 8 files changed, 74 insertions(+), 56 deletions(-) diff --git a/pymisp/tools/abstractgenerator.py b/pymisp/tools/abstractgenerator.py index 2703c46..a3ca26f 100644 --- a/pymisp/tools/abstractgenerator.py +++ b/pymisp/tools/abstractgenerator.py @@ -2,11 +2,14 @@ from __future__ import annotations -from .. import MISPObject -from ..exceptions import InvalidMISPObject from datetime import datetime, date from dateutil.parser import parse +from typing import Any + +from .. import MISPObject +from ..exceptions import InvalidMISPObject + class AbstractMISPObjectGenerator(MISPObject): @@ -21,7 +24,7 @@ class AbstractMISPObjectGenerator(MISPObject): except ValueError: return False - def _sanitize_timestamp(self, timestamp: datetime | date | dict | str | int | float | None = None) -> datetime: + def _sanitize_timestamp(self, timestamp: datetime | date | dict[str, Any] | str | int | float | None = None) -> datetime: if not timestamp: return datetime.now() @@ -42,9 +45,9 @@ class AbstractMISPObjectGenerator(MISPObject): else: raise Exception(f'Unable to convert {timestamp} to a datetime.') - def generate_attributes(self): + def generate_attributes(self) -> None: """Contains the logic where all the values of the object are gathered""" - if hasattr(self, '_parameters'): + if hasattr(self, '_parameters') and self._definition is not None: for object_relation in self._definition['attributes']: value = self._parameters.pop(object_relation, None) if not value: diff --git a/pymisp/tools/asnobject.py b/pymisp/tools/asnobject.py index a51c0b3..685da7a 100644 --- a/pymisp/tools/asnobject.py +++ b/pymisp/tools/asnobject.py @@ -13,12 +13,12 @@ logger = logging.getLogger('pymisp') class ASNObject(AbstractMISPObjectGenerator): - def __init__(self, parameters: dict[str, Any], strict: bool = True, **kwargs) -> None: + def __init__(self, parameters: dict[str, Any], strict: bool = True, **kwargs) -> None: # type: ignore[no-untyped-def] super().__init__('asn', strict=strict, **kwargs) self._parameters = parameters self.generate_attributes() - def generate_attributes(self): + def generate_attributes(self) -> None: first = self._sanitize_timestamp(self._parameters.pop('first-seen', None)) self._parameters['first-seen'] = first last = self._sanitize_timestamp(self._parameters.pop('last-seen', None)) diff --git a/pymisp/tools/create_misp_object.py b/pymisp/tools/create_misp_object.py index 31e7048..2efcb90 100644 --- a/pymisp/tools/create_misp_object.py +++ b/pymisp/tools/create_misp_object.py @@ -5,9 +5,8 @@ from __future__ import annotations import logging from io import BytesIO -from typing import Any +from typing import Any, TYPE_CHECKING -from . import FileObject, PEObject, ELFObject, MachOObject, PESectionObject, ELFSectionObject, MachOSectionObject from ..exceptions import MISPObjectException logger = logging.getLogger('pymisp') @@ -28,6 +27,9 @@ except AttributeError: except ImportError: HAS_LIEF = False +if TYPE_CHECKING: + from . import FileObject, PEObject, ELFObject, MachOObject, PESectionObject, ELFSectionObject, MachOSectionObject + class FileTypeNotImplemented(MISPObjectException): pass diff --git a/pymisp/tools/csvloader.py b/pymisp/tools/csvloader.py index 7d68f88..e0452ec 100644 --- a/pymisp/tools/csvloader.py +++ b/pymisp/tools/csvloader.py @@ -3,7 +3,6 @@ from __future__ import annotations from pathlib import Path -from typing import List, Optional import csv from pymisp import MISPObject @@ -11,8 +10,9 @@ from pymisp import MISPObject class CSVLoader(): - def __init__(self, template_name: str, csv_path: Path, fieldnames: list[str] | None = None, has_fieldnames=False, - delimiter: str = ',', quotechar: str = '"'): + def __init__(self, template_name: str, csv_path: Path, + fieldnames: list[str] | None = None, has_fieldnames: bool=False, + delimiter: str = ',', quotechar: str = '"') -> None: self.template_name = template_name self.delimiter = delimiter self.quotechar = quotechar @@ -26,7 +26,7 @@ class CSVLoader(): else: self.has_fieldnames = has_fieldnames - def load(self): + def load(self) -> list[MISPObject]: objects = [] @@ -44,7 +44,7 @@ class CSVLoader(): # Check if the CSV file has a header, and if it matches with the object template tmp_object = MISPObject(self.template_name) - if not tmp_object._definition['attributes']: + if not tmp_object._definition or not tmp_object._definition['attributes']: raise Exception(f'Unable to find the object template ({self.template_name}), impossible to create objects.') allowed_fieldnames = list(tmp_object._definition['attributes'].keys()) for fieldname in self.fieldnames: diff --git a/pymisp/tools/domainipobject.py b/pymisp/tools/domainipobject.py index 1bed317..2269342 100644 --- a/pymisp/tools/domainipobject.py +++ b/pymisp/tools/domainipobject.py @@ -2,20 +2,23 @@ from __future__ import annotations -from .abstractgenerator import AbstractMISPObjectGenerator import logging +from typing import Any + +from .abstractgenerator import AbstractMISPObjectGenerator + logger = logging.getLogger('pymisp') class DomainIPObject(AbstractMISPObjectGenerator): - def __init__(self, parameters: dict, strict: bool = True, **kwargs): + def __init__(self, parameters: dict[str, Any], strict: bool = True, **kwargs) -> None: # type: ignore[no-untyped-def] super().__init__('domain-ip', strict=strict, **kwargs) self._parameters = parameters self.generate_attributes() - def generate_attributes(self): + def generate_attributes(self) -> None: first = self._sanitize_timestamp(self._parameters.pop('first-seen', None)) self._parameters['first-seen'] = first last = self._sanitize_timestamp(self._parameters.pop('last-seen', None)) diff --git a/pymisp/tools/emailobject.py b/pymisp/tools/emailobject.py index 21e2478..25a85a3 100644 --- a/pymisp/tools/emailobject.py +++ b/pymisp/tools/emailobject.py @@ -10,10 +10,11 @@ from email import policy, message_from_bytes from email.message import EmailMessage from io import BytesIO from pathlib import Path -from typing import Union, List, Tuple, Dict, cast, Any, Optional +from typing import cast, Any from extract_msg import openMsg from extract_msg.msg_classes import MessageBase +from extract_msg.attachments import AttachmentBase, SignedAttachment from extract_msg.properties import FixedLengthProp from RTFDE.exceptions import MalformedEncapsulatedRtf, NotEncapsulatedRtf # type: ignore from RTFDE.deencapsulate import DeEncapsulator # type: ignore @@ -30,15 +31,14 @@ class MISPMsgConverstionError(MISPObjectException): class EMailObject(AbstractMISPObjectGenerator): - def __init__(self, filepath: Path | str | None=None, pseudofile: BytesIO | None=None, - attach_original_email: bool = True, **kwargs): + def __init__(self, filepath: Path | str | None=None, pseudofile: BytesIO | None=None, # type: ignore[no-untyped-def] + attach_original_email: bool = True, **kwargs) -> None: super().__init__('email', **kwargs) self.attach_original_email = attach_original_email self.encapsulated_body: str | None = None self.eml_from_msg: bool | None = None - self.raw_emails: dict[str, BytesIO | None] = {'msg': None, - 'eml': None} + self.raw_emails: dict[str, BytesIO | None] = {'msg': None, 'eml': None} self.__pseudofile = self.create_pseudofile(filepath, pseudofile) self.email = self.parse_email() @@ -103,7 +103,7 @@ class EMailObject(AbstractMISPObjectGenerator): eml = self._build_eml(message, body, attachments) return eml - def _extract_msg_objects(self, msg_obj: MessageBase) -> tuple[EmailMessage, dict, list[Any]]: + def _extract_msg_objects(self, msg_obj: MessageBase) -> tuple[EmailMessage, dict[str, Any], list[AttachmentBase] | list[SignedAttachment]]: """Extracts email objects needed to construct an eml from a msg.""" message: EmailMessage = email.message_from_string(msg_obj.header.as_string(), policy=policy.default) # type: ignore body = {} @@ -151,13 +151,12 @@ class EMailObject(AbstractMISPObjectGenerator): attachments = msg_obj.attachments return message, body, attachments - def _build_eml(self, message: EmailMessage, body: dict, attachments: list) -> EmailMessage: + def _build_eml(self, message: EmailMessage, body: dict[str, Any], attachments: list[Any]) -> EmailMessage: """Constructs an eml file from objects extracted from a msg.""" # Order the body objects by increasing complexity and toss any missing objects - body_objects: list[dict] = [body.get('text', {}), - body.get('html', {}), - body.get('rtf', {})] - body_objects = [i for i in body_objects if i != {}] + body_objects: list[dict[str, Any]] = [i for i in [body.get('text'), + body.get('html'), + body.get('rtf')] if i is not None] # If this a non-multipart email then we only need to attach the payload if message.get_content_maintype() != 'multipart': for _body in body_objects: @@ -225,7 +224,7 @@ class EMailObject(AbstractMISPObjectGenerator): return message @staticmethod - def _update_content_disp_properties(msg_attch, eml_attch): + def _update_content_disp_properties(msg_attch: AttachmentBase, eml_attch: EmailMessage) -> None: """Set Content-Disposition params on binary eml objects You currently have to set non-filename content-disp params by hand in python. @@ -235,7 +234,7 @@ class EMailObject(AbstractMISPObjectGenerator): for num, name in attch_cont_disp_props.items(): try: eml_attch.set_param(name, - email.utils.format_datetime(msg_attch.props[num].value), + email.utils.format_datetime(msg_attch.props.getValue(num)), header='Content-Disposition') except KeyError: # It's fine if they don't have those values @@ -256,7 +255,7 @@ class EMailObject(AbstractMISPObjectGenerator): pass return to_return - def generate_attributes(self): + def generate_attributes(self) -> None: # Attach original & Converted if self.attach_original_email is not None: @@ -269,20 +268,28 @@ class EMailObject(AbstractMISPObjectGenerator): message = self.email - for _pref, body in message._find_body(message, preferencelist=['plain', 'html']): + if body := message.get_body(preferencelist=['plain']): comment = f"{body.get_content_type()} body" if self.encapsulated_body == body.get_content_type(): comment += " De-Encapsulated from RTF in original msg." self.add_attribute("email-body", - body.get_content(), + body.as_string(), + comment=comment) + + if body := message.get_body(preferencelist=['html']): + comment = f"{body.get_content_type()} body" + if self.encapsulated_body == body.get_content_type(): + comment += " De-Encapsulated from RTF in original msg." + self.add_attribute("email-body", + body.as_string(), comment=comment) headers = [f"{k}: {v}" for k, v in message.items()] if headers: self.add_attribute("header", "\n".join(headers)) - if "Date" in message and message.get('date').datetime is not None: - self.add_attribute("send-date", message.get('date').datetime) + if "Date" in message and message['date'].datetime is not None: + self.add_attribute("send-date", message['date'].datetime) if "To" in message: self.__add_emails("to", message["To"]) @@ -326,9 +333,9 @@ class EMailObject(AbstractMISPObjectGenerator): self.__generate_received() - def __add_emails(self, typ: str, data: str, insert_display_names: bool = True): - addresses = [] - display_names = [] + def __add_emails(self, typ: str, data: str, insert_display_names: bool = True) -> None: + addresses: list[dict[str, str]] = [] + display_names: list[dict[str, str]] = [] for realname, address in email.utils.getaddresses([data]): if address and realname: @@ -341,16 +348,17 @@ class EMailObject(AbstractMISPObjectGenerator): if realname: display_names.append({"value": realname, "comment": f"{realname} <{address}>"}) - if addresses: - self.add_attributes(typ, *addresses) + for a in addresses: + self.add_attribute(typ, **a) if insert_display_names and display_names: try: - self.add_attributes(f"{typ}-display-name", *display_names) + for d in display_names: + self.add_attribute(f"{typ}-display-name", **d) except NewAttributeError: # email object doesn't support display name for all email addrs pass - def __generate_received(self): + def __generate_received(self) -> None: """ Extract IP addresses from received headers that are not private. Also extract hostnames or domains. """ diff --git a/pymisp/tools/genericgenerator.py b/pymisp/tools/genericgenerator.py index dbe6d50..7279ca3 100644 --- a/pymisp/tools/genericgenerator.py +++ b/pymisp/tools/genericgenerator.py @@ -2,14 +2,15 @@ from __future__ import annotations +from typing import Any + from .abstractgenerator import AbstractMISPObjectGenerator -from typing import List class GenericObjectGenerator(AbstractMISPObjectGenerator): # FIXME: this method is different from the master one, and that's probably not a good idea. - def generate_attributes(self, attributes: list[dict]): # type: ignore + def generate_attributes(self, attributes: list[dict[str, Any]]) -> None: """Generates MISPObjectAttributes from a list of dictionaries. Each entry if the list must be in one of the two following formats: * {: } diff --git a/pymisp/tools/microblogobject.py b/pymisp/tools/microblogobject.py index 089877c..63d20a1 100644 --- a/pymisp/tools/microblogobject.py +++ b/pymisp/tools/microblogobject.py @@ -2,22 +2,23 @@ from __future__ import annotations +import logging +from typing import Any # NOTE: Reference on how this module is used: https://vvx7.io/posts/2020/05/misp-slack-bot/ from .abstractgenerator import AbstractMISPObjectGenerator -import logging logger = logging.getLogger('pymisp') class MicroblogObject(AbstractMISPObjectGenerator): - def __init__(self, parameters: dict, strict: bool = True, **kwargs): + def __init__(self, parameters: dict[str, Any], strict: bool = True, **kwargs): # type: ignore[no-untyped-def] super().__init__('microblog', strict=strict, **kwargs) self._parameters = parameters self.generate_attributes() - def generate_attributes(self): + def generate_attributes(self) -> None: # Raw post. if 'post' in self._parameters: self.add_attribute('post', value=self._parameters['post']) @@ -33,7 +34,7 @@ class MicroblogObject(AbstractMISPObjectGenerator): # Original URL location of the microblog post (potentially malicious. if 'url' in self._parameters: if isinstance(self._parameters.get('url'), list): - for i in self._parameters.get('url'): + for i in self._parameters['url']: self.add_attribute('url', value=i) else: self.add_attribute('url', value=self._parameters['url']) @@ -41,7 +42,7 @@ class MicroblogObject(AbstractMISPObjectGenerator): # Archive of the original document (Internet Archive, Archive.is, etc). if 'archive' in self._parameters: if isinstance(self._parameters.get('archive'), list): - for i in self._parameters.get('archive'): + for i in self._parameters['archive']: self.add_attribute('archive', value=i) else: self.add_attribute('archive', value=self._parameters['archive']) @@ -75,7 +76,7 @@ class MicroblogObject(AbstractMISPObjectGenerator): "Instagram", "Forum", "Other"] if 'type' in self._parameters: if isinstance(self._parameters.get('type'), list): - for i in self._parameters.get('type'): + for i in self._parameters['type']: if i in type_allowed_values: self.add_attribute('type', value=i) else: @@ -86,7 +87,7 @@ class MicroblogObject(AbstractMISPObjectGenerator): type_allowed_values = ["Informative", "Malicious", "Misinformation", "Disinformation", "Unknown"] if 'state' in self._parameters: if isinstance(self._parameters.get('state'), list): - for i in self._parameters.get('state'): + for i in self._parameters['state']: if i in type_allowed_values: self.add_attribute('state', value=i) else: @@ -101,7 +102,7 @@ class MicroblogObject(AbstractMISPObjectGenerator): type_allowed_values = ["Verified", "Unverified", "Unknown"] if 'verified-username' in self._parameters: if isinstance(self._parameters.get('verified-username'), list): - for i in self._parameters.get('verified-username'): + for i in self._parameters['verified-username']: if i in type_allowed_values: self.add_attribute('verified-username', value=i) else: @@ -111,7 +112,7 @@ class MicroblogObject(AbstractMISPObjectGenerator): # embedded-link. if 'embedded-link' in self._parameters: if isinstance(self._parameters.get('embedded-link'), list): - for i in self._parameters.get('embedded-link'): + for i in self._parameters['embedded-link']: self.add_attribute('embedded-link', value=i) else: self.add_attribute('embedded-link', value=self._parameters['embedded-link']) @@ -119,7 +120,7 @@ class MicroblogObject(AbstractMISPObjectGenerator): # embedded-safe-link if 'embedded-safe-link' in self._parameters: if isinstance(self._parameters.get('embedded-safe-link'), list): - for i in self._parameters.get('embedded-safe-link'): + for i in self._parameters['embedded-safe-link']: self.add_attribute('embedded-safe-link', value=i) else: self.add_attribute('embedded-safe-link', value=self._parameters['embedded-safe-link']) @@ -127,7 +128,7 @@ class MicroblogObject(AbstractMISPObjectGenerator): # Hashtag into the microblog post. if 'hashtag' in self._parameters: if isinstance(self._parameters.get('hashtag'), list): - for i in self._parameters.get('hashtag'): + for i in self._parameters['hashtag']: self.add_attribute('hashtag', value=i) else: self.add_attribute('hashtag', value=self._parameters['hashtag']) @@ -135,7 +136,7 @@ class MicroblogObject(AbstractMISPObjectGenerator): # username quoted if 'username-quoted' in self._parameters: if isinstance(self._parameters.get('username-quoted'), list): - for i in self._parameters.get('username-quoted'): + for i in self._parameters['username-quoted']: self.add_attribute('username-quoted', value=i) else: self.add_attribute('username-quoted', value=self._parameters['username-quoted']) From 1da0d5adc148e994d47c3964f857b014db3b630c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Vinot?= Date: Thu, 1 Feb 2024 14:40:12 +0100 Subject: [PATCH 52/80] chg: Add more strict typing, not done yet. --- mypy.ini | 2 +- pymisp/__init__.py | 1 - pymisp/abstract.py | 8 +- pymisp/api.py | 2 +- pymisp/mispevent.py | 18 +- pymisp/tools/_psl_faup.py | 119 +++++---- pymisp/tools/emailobject.py | 8 +- pymisp/tools/ext_lookups.py | 8 +- pymisp/tools/fail2banobject.py | 9 +- pymisp/tools/feed.py | 3 +- pymisp/tools/fileobject.py | 10 +- pymisp/tools/genericgenerator.py | 2 +- pymisp/tools/geolocationobject.py | 9 +- pymisp/tools/git_vuln_finder_object.py | 9 +- pymisp/tools/load_warninglists.py | 17 +- pymisp/tools/neo4j.py | 11 +- pymisp/tools/sbsignatureobject.py | 4 +- pymisp/tools/sshauthkeyobject.py | 15 +- pymisp/tools/stix.py | 35 --- pymisp/tools/update_objects.py | 2 +- pymisp/tools/urlobject.py | 8 +- pymisp/tools/vehicleobject.py | 16 +- pymisp/tools/vtreportobject.py | 12 +- tests/test_emailobject.py | 28 +- tests/test_fileobject.py | 2 +- tests/test_mispevent.py | 134 +++++----- tests/testlive_comprehensive.py | 343 ++++++++++++++----------- 27 files changed, 442 insertions(+), 393 deletions(-) delete mode 100644 pymisp/tools/stix.py diff --git a/mypy.ini b/mypy.ini index f00223e..b4fb74d 100644 --- a/mypy.ini +++ b/mypy.ini @@ -3,7 +3,7 @@ strict = True warn_return_any = False show_error_context = True pretty = True -exclude = feed-generator|examples|pymisp/tools|pymisp/data|tests|docs +exclude = tests/testlive_comprehensive.py|tests/testlive_sync.py|feed-generator|examples|pymisp/data|docs|pymisp/tools/openioc.py|pymisp/tools/reportlab_generator.py|tests/test_reportlab.py # Stuff to remove gradually # disallow_untyped_defs = False diff --git a/pymisp/__init__.py b/pymisp/__init__.py index 9599bdc..a235ce9 100644 --- a/pymisp/__init__.py +++ b/pymisp/__init__.py @@ -42,7 +42,6 @@ try: MISPGalaxyClusterElement, MISPGalaxyClusterRelation) from .tools import AbstractMISPObjectGenerator # noqa from .tools import Neo4j # noqa - from .tools import stix # noqa from .tools import openioc # noqa from .tools import ext_lookups # noqa from .tools import update_objects # noqa diff --git a/pymisp/abstract.py b/pymisp/abstract.py index c4de2e9..8ca7cae 100644 --- a/pymisp/abstract.py +++ b/pymisp/abstract.py @@ -8,7 +8,7 @@ from deprecated import deprecated # type: ignore from json import JSONEncoder from uuid import UUID from abc import ABCMeta -from enum import Enum +from enum import Enum, IntEnum from typing import Any, Mapping from collections.abc import MutableMapping from functools import lru_cache @@ -46,7 +46,7 @@ class MISPFileCache: return data -class Distribution(Enum): +class Distribution(IntEnum): your_organisation_only = 0 this_community_only = 1 connected_communities = 2 @@ -55,14 +55,14 @@ class Distribution(Enum): inherit = 5 -class ThreatLevel(Enum): +class ThreatLevel(IntEnum): high = 1 medium = 2 low = 3 undefined = 4 -class Analysis(Enum): +class Analysis(IntEnum): initial = 0 ongoing = 1 completed = 2 diff --git a/pymisp/api.py b/pymisp/api.py index 583239c..d19a0ba 100644 --- a/pymisp/api.py +++ b/pymisp/api.py @@ -1012,7 +1012,7 @@ class PyMISP: to_return.append(s) return to_return - def add_sighting(self, sighting: MISPSighting, + def add_sighting(self, sighting: MISPSighting | dict[str, Any], attribute: MISPAttribute | int | str | UUID | None = None, pythonify: bool = False) -> dict[str, Any] | MISPSighting: """Add a new sighting (globally, or to a specific attribute): https://www.misp-project.org/openapi/#tag/Sightings/operation/addSighting and https://www.misp-project.org/openapi/#tag/Sightings/operation/getSightingsByEventId diff --git a/pymisp/mispevent.py b/pymisp/mispevent.py index ac1361c..a283201 100644 --- a/pymisp/mispevent.py +++ b/pymisp/mispevent.py @@ -13,7 +13,7 @@ from collections import defaultdict import logging import hashlib from pathlib import Path -from typing import IO, Any +from typing import IO, Any, Sequence import warnings try: @@ -1010,15 +1010,17 @@ class MISPObject(AbstractMISP): self.edited = True return attribute - def add_attributes(self, object_relation: str, *attributes: list[dict[str, Any] | MISPAttribute]) -> list[MISPAttribute | None]: + def add_attributes(self, object_relation: str, *attributes: Sequence[str | dict[str, Any] | MISPAttribute]) -> list[MISPAttribute | None]: '''Add multiple attributes with the same object_relation. Helper for object_relation when multiple is True in the template. It is the same as calling multiple times add_attribute with the same object_relation. ''' to_return = [] for attribute in attributes: - if isinstance(attribute, dict): - a = self.add_attribute(object_relation, **attribute) + if isinstance(attribute, MISPAttribute): + a = self.add_attribute(object_relation, **attribute.to_dict()) + elif isinstance(attribute, dict): + a = self.add_attribute(object_relation, **attribute) # type: ignore[misc] else: a = self.add_attribute(object_relation, value=attribute) to_return.append(a) @@ -1256,6 +1258,10 @@ class MISPGalaxyCluster(AbstractMISP): :type cluster_relations: list[MISPGalaxyClusterRelation], optional """ + id: int | str | None + tag_name: str + galaxy_id: str | None + def __init__(self) -> None: super().__init__() self.Galaxy: MISPGalaxy @@ -1405,6 +1411,8 @@ class MISPGalaxyCluster(AbstractMISP): class MISPGalaxy(AbstractMISP): """Galaxy class, used to view a galaxy and respective clusters""" + id: str | None + def __init__(self) -> None: super().__init__() self.GalaxyCluster: list[MISPGalaxyCluster] = [] @@ -2048,6 +2056,8 @@ class MISPObjectTemplate(AbstractMISP): class MISPUser(AbstractMISP): + authkey: str + def __init__(self, **kwargs: dict[str, Any]) -> None: super().__init__(**kwargs) self.email: str diff --git a/pymisp/tools/_psl_faup.py b/pymisp/tools/_psl_faup.py index 9a33bfd..388fed4 100644 --- a/pymisp/tools/_psl_faup.py +++ b/pymisp/tools/_psl_faup.py @@ -6,7 +6,7 @@ import ipaddress import socket import idna from publicsuffixlist import PublicSuffixList # type: ignore -from urllib.parse import urlparse, urlunparse +from urllib.parse import urlparse, urlunparse, ParseResult class UrlNotDecoded(Exception): @@ -18,20 +18,20 @@ class PSLFaup: Fake Faup Python Library using PSL for Windows support """ - def __init__(self): + def __init__(self) -> None: self.decoded = False self.psl = PublicSuffixList() - self._url = None - self._retval = {} - self.ip_as_host = False + self._url: ParseResult | None = None + self._retval: dict[str, str | int | None | bytes] = {} + self.ip_as_host = '' - def _clear(self): + def _clear(self) -> None: self.decoded = False self._url = None self._retval = {} - self.ip_as_host = False + self.ip_as_host = '' - def decode(self, url) -> None: + def decode(self, url: str) -> None: """ This function creates a dict of all the url fields. :param url: The URL to normalize @@ -43,10 +43,15 @@ class PSLFaup: url = '//' + url self._url = urlparse(url) - self.ip_as_host = False + if self._url is None: + raise UrlNotDecoded("Unable to parse URL") + + self.ip_as_host = '' + if self._url.hostname is None: + raise UrlNotDecoded("Unable to parse URL") hostname = _ensure_str(self._url.hostname) try: - ipv4_bytes = socket.inet_aton(_ensure_str(hostname)) + ipv4_bytes = socket.inet_aton(hostname) ipv4 = ipaddress.IPv4Address(ipv4_bytes) self.ip_as_host = ipv4.compressed except (OSError, ValueError): @@ -61,61 +66,70 @@ class PSLFaup: self._retval = {} @property - def url(self): - if not self.decoded: + def url(self) -> bytes | None: + if not self.decoded or not self._url: raise UrlNotDecoded("You must call faup.decode() first") - netloc = self.get_host() + ('' if self.get_port() is None else f':{self.get_port()}') - return _ensure_bytes( - urlunparse( - (self.get_scheme(), netloc, self.get_resource_path(), - '', self.get_query_string(), self.get_fragment(),) + if host := self.get_host(): + netloc = host + ('' if self.get_port() is None else f':{self.get_port()}') + return _ensure_bytes( + urlunparse( + (self.get_scheme(), netloc, self.get_resource_path(), + '', self.get_query_string(), self.get_fragment(),) + ) ) - ) + return None - def get_scheme(self): + def get_scheme(self) -> str: """ Get the scheme of the url given in the decode function :returns: The URL scheme """ - if not self.decoded: + if not self.decoded or not self._url: raise UrlNotDecoded("You must call faup.decode() first") - return _ensure_str(self._url.scheme) + return _ensure_str(self._url.scheme if self._url.scheme else '') - def get_credential(self): - if not self.decoded: + def get_credential(self) -> str | None: + if not self.decoded or not self._url: raise UrlNotDecoded("You must call faup.decode() first") - if self._url.password: + if self._url.username and self._url.password: return _ensure_str(self._url.username) + ':' + _ensure_str(self._url.password) if self._url.username: return _ensure_str(self._url.username) + return None - def get_subdomain(self): - if not self.decoded: + def get_subdomain(self) -> str | None: + if not self.decoded or not self._url: raise UrlNotDecoded("You must call faup.decode() first") if self.get_host() is not None and not self.ip_as_host: - if self.get_domain() in self.get_host(): - return self.get_host().rsplit(self.get_domain(), 1)[0].rstrip('.') or None + domain = self.get_domain() + host = self.get_host() + if domain and host and domain in host: + return host.rsplit(domain, 1)[0].rstrip('.') or None + return None - def get_domain(self): - if not self.decoded: + def get_domain(self) -> str | None: + if not self.decoded or not self._url: raise UrlNotDecoded("You must call faup.decode() first") if self.get_host() is not None and not self.ip_as_host: return self.psl.privatesuffix(self.get_host()) + return None - def get_domain_without_tld(self): - if not self.decoded: + def get_domain_without_tld(self) -> str | None: + if not self.decoded or not self._url: raise UrlNotDecoded("You must call faup.decode() first") if self.get_tld() is not None and not self.ip_as_host: - return self.get_domain().rsplit(self.get_tld(), 1)[0].rstrip('.') + if domain := self.get_domain(): + return domain.rsplit(self.get_tld(), 1)[0].rstrip('.') + return None - def get_host(self): - if not self.decoded: + def get_host(self) -> str | None: + if not self.decoded or not self._url: raise UrlNotDecoded("You must call faup.decode() first") if self._url.hostname is None: @@ -125,45 +139,48 @@ class PSLFaup: else: return _ensure_str(idna.encode(self._url.hostname, uts46=True)) - def get_unicode_host(self): - if not self.decoded: + def get_unicode_host(self) -> str | None: + if not self.decoded or not self._url: raise UrlNotDecoded("You must call faup.decode() first") if not self.ip_as_host: - return idna.decode(self.get_host(), uts46=True) + if host := self.get_host(): + return idna.decode(host, uts46=True) + return None - def get_tld(self): - if not self.decoded: + def get_tld(self) -> str | None: + if not self.decoded or not self._url: raise UrlNotDecoded("You must call faup.decode() first") if self.get_host() is not None and not self.ip_as_host: return self.psl.publicsuffix(self.get_host()) + return None - def get_port(self): - if not self.decoded: + def get_port(self) -> int | None: + if not self.decoded or not self._url: raise UrlNotDecoded("You must call faup.decode() first") return self._url.port - def get_resource_path(self): - if not self.decoded: + def get_resource_path(self) -> str: + if not self.decoded or not self._url: raise UrlNotDecoded("You must call faup.decode() first") return _ensure_str(self._url.path) - def get_query_string(self): - if not self.decoded: + def get_query_string(self) -> str: + if not self.decoded or not self._url: raise UrlNotDecoded("You must call faup.decode() first") return _ensure_str(self._url.query) - def get_fragment(self): - if not self.decoded: + def get_fragment(self) -> str: + if not self.decoded or not self._url: raise UrlNotDecoded("You must call faup.decode() first") return _ensure_str(self._url.fragment) - def get(self): + def get(self) -> dict[str, str | int | None | bytes]: self._retval["scheme"] = self.get_scheme() self._retval["tld"] = self.get_tld() self._retval["domain"] = self.get_domain() @@ -178,14 +195,14 @@ class PSLFaup: return self._retval -def _ensure_bytes(binary) -> bytes: +def _ensure_bytes(binary: str | bytes) -> bytes: if isinstance(binary, bytes): return binary else: return binary.encode('utf-8') -def _ensure_str(string) -> str: +def _ensure_str(string: str | bytes) -> str: if isinstance(string, str): return string else: diff --git a/pymisp/tools/emailobject.py b/pymisp/tools/emailobject.py index 25a85a3..731a3bc 100644 --- a/pymisp/tools/emailobject.py +++ b/pymisp/tools/emailobject.py @@ -31,7 +31,7 @@ class MISPMsgConverstionError(MISPObjectException): class EMailObject(AbstractMISPObjectGenerator): - def __init__(self, filepath: Path | str | None=None, pseudofile: BytesIO | None=None, # type: ignore[no-untyped-def] + def __init__(self, filepath: Path | str | None=None, pseudofile: BytesIO | bytes | None=None, # type: ignore[no-untyped-def] attach_original_email: bool = True, **kwargs) -> None: super().__init__('email', **kwargs) @@ -79,11 +79,11 @@ class EMailObject(AbstractMISPObjectGenerator): return eml except UnicodeDecodeError: pass - raise PyMISPNotImplementedYet("EmailObject does not know how to decode data passed to it. Object may not be an email. If this is an email please submit it as an issue to PyMISP so we can add support.") + raise InvalidMISPObject("EmailObject does not know how to decode data passed to it. Object may not be an email. If this is an email please submit it as an issue to PyMISP so we can add support.") @staticmethod def create_pseudofile(filepath: Path | str | None = None, - pseudofile: BytesIO | None = None) -> BytesIO: + pseudofile: BytesIO | bytes | None = None) -> BytesIO: """Creates a pseudofile using directly passed data or data loaded from file path. """ if filepath: @@ -91,6 +91,8 @@ class EMailObject(AbstractMISPObjectGenerator): return BytesIO(f.read()) elif pseudofile and isinstance(pseudofile, BytesIO): return pseudofile + elif pseudofile and isinstance(pseudofile, bytes): + return BytesIO(pseudofile) else: raise InvalidMISPObject('File buffer (BytesIO) or a path is required.') diff --git a/pymisp/tools/ext_lookups.py b/pymisp/tools/ext_lookups.py index e1bf7c6..c4e81ac 100644 --- a/pymisp/tools/ext_lookups.py +++ b/pymisp/tools/ext_lookups.py @@ -15,7 +15,7 @@ except ImportError: has_pymispgalaxies = False -def revert_tag_from_galaxies(tag): +def revert_tag_from_galaxies(tag: str) -> list[str]: clusters = Clusters() try: return clusters.revert_machinetag(tag) @@ -23,7 +23,7 @@ def revert_tag_from_galaxies(tag): return [] -def revert_tag_from_taxonomies(tag): +def revert_tag_from_taxonomies(tag: str) -> list[str]: taxonomies = Taxonomies() try: return taxonomies.revert_machinetag(tag) @@ -31,7 +31,7 @@ def revert_tag_from_taxonomies(tag): return [] -def search_taxonomies(query): +def search_taxonomies(query: str) -> list[str]: taxonomies = Taxonomies() found = taxonomies.search(query) if not found: @@ -39,6 +39,6 @@ def search_taxonomies(query): return found -def search_galaxies(query): +def search_galaxies(query: str) -> list[str]: clusters = Clusters() return clusters.search(query) diff --git a/pymisp/tools/fail2banobject.py b/pymisp/tools/fail2banobject.py index b714e27..a8e3fda 100644 --- a/pymisp/tools/fail2banobject.py +++ b/pymisp/tools/fail2banobject.py @@ -2,20 +2,23 @@ from __future__ import annotations -from .abstractgenerator import AbstractMISPObjectGenerator import logging +from typing import Any + +from .abstractgenerator import AbstractMISPObjectGenerator + logger = logging.getLogger('pymisp') class Fail2BanObject(AbstractMISPObjectGenerator): - def __init__(self, parameters: dict, strict: bool = True, **kwargs): + def __init__(self, parameters: dict[str, Any], strict: bool = True, **kwargs): # type: ignore[no-untyped-def] super().__init__('fail2ban', strict=strict, **kwargs) self._parameters = parameters self.generate_attributes() - def generate_attributes(self): + def generate_attributes(self) -> None: timestamp = self._sanitize_timestamp(self._parameters.pop('processing-timestamp', None)) self._parameters['processing-timestamp'] = timestamp super().generate_attributes() diff --git a/pymisp/tools/feed.py b/pymisp/tools/feed.py index 9f7c084..0452a25 100644 --- a/pymisp/tools/feed.py +++ b/pymisp/tools/feed.py @@ -5,10 +5,9 @@ from __future__ import annotations from pathlib import Path from pymisp import MISPEvent import json -from typing import List -def feed_meta_generator(path: Path): +def feed_meta_generator(path: Path) -> None: manifests = {} hashes: list[str] = [] diff --git a/pymisp/tools/fileobject.py b/pymisp/tools/fileobject.py index 9a8c8be..f8b277e 100644 --- a/pymisp/tools/fileobject.py +++ b/pymisp/tools/fileobject.py @@ -30,7 +30,9 @@ except ImportError: class FileObject(AbstractMISPObjectGenerator): - def __init__(self, filepath: Path | str | None = None, pseudofile: BytesIO | bytes | None = None, filename: str | None = None, **kwargs) -> None: + def __init__(self, filepath: Path | str | None = None, # type: ignore[no-untyped-def] + pseudofile: BytesIO | bytes | None = None, + filename: str | None = None, **kwargs) -> None: super().__init__('file', **kwargs) if not HAS_PYDEEP: logger.warning("pydeep is missing, please install pymisp this way: pip install pymisp[fileobjects]") @@ -55,10 +57,10 @@ class FileObject(AbstractMISPObjectGenerator): self.__data = self.__pseudofile.getvalue() self.generate_attributes() - def generate_attributes(self): + def generate_attributes(self) -> None: self.add_attribute('filename', value=self.__filename) - size = self.add_attribute('size-in-bytes', value=len(self.__data)) - if int(size.value) > 0: + self.add_attribute('size-in-bytes', value=len(self.__data)) + if len(self.__data) > 0: self.add_attribute('entropy', value=self.__entropy_H(self.__data)) self.add_attribute('md5', value=md5(self.__data).hexdigest()) self.add_attribute('sha1', value=sha1(self.__data).hexdigest()) diff --git a/pymisp/tools/genericgenerator.py b/pymisp/tools/genericgenerator.py index 7279ca3..811f604 100644 --- a/pymisp/tools/genericgenerator.py +++ b/pymisp/tools/genericgenerator.py @@ -10,7 +10,7 @@ from .abstractgenerator import AbstractMISPObjectGenerator class GenericObjectGenerator(AbstractMISPObjectGenerator): # FIXME: this method is different from the master one, and that's probably not a good idea. - def generate_attributes(self, attributes: list[dict[str, Any]]) -> None: + def generate_attributes(self, attributes: list[dict[str, Any]]) -> None: # type: ignore[override] """Generates MISPObjectAttributes from a list of dictionaries. Each entry if the list must be in one of the two following formats: * {: } diff --git a/pymisp/tools/geolocationobject.py b/pymisp/tools/geolocationobject.py index 80a2aa1..fc995c9 100644 --- a/pymisp/tools/geolocationobject.py +++ b/pymisp/tools/geolocationobject.py @@ -2,20 +2,23 @@ from __future__ import annotations -from .abstractgenerator import AbstractMISPObjectGenerator import logging +from typing import Any + +from .abstractgenerator import AbstractMISPObjectGenerator + logger = logging.getLogger('pymisp') class GeolocationObject(AbstractMISPObjectGenerator): - def __init__(self, parameters: dict, strict: bool = True, **kwargs): + def __init__(self, parameters: dict[str, Any], strict: bool = True, **kwargs) -> None: # type: ignore[no-untyped-def] super().__init__('geolocation', strict=strict, **kwargs) self._parameters = parameters self.generate_attributes() - def generate_attributes(self): + def generate_attributes(self) -> None: first = self._sanitize_timestamp(self._parameters.pop('first-seen', None)) self._parameters['first-seen'] = first last = self._sanitize_timestamp(self._parameters.pop('last-seen', None)) diff --git a/pymisp/tools/git_vuln_finder_object.py b/pymisp/tools/git_vuln_finder_object.py index 50e3b72..21ec512 100644 --- a/pymisp/tools/git_vuln_finder_object.py +++ b/pymisp/tools/git_vuln_finder_object.py @@ -2,20 +2,23 @@ from __future__ import annotations -from .abstractgenerator import AbstractMISPObjectGenerator import logging +from typing import Any + +from .abstractgenerator import AbstractMISPObjectGenerator + logger = logging.getLogger('pymisp') class GitVulnFinderObject(AbstractMISPObjectGenerator): - def __init__(self, parameters: dict, strict: bool = True, **kwargs): + def __init__(self, parameters: dict[str, Any], strict: bool = True, **kwargs) -> None: # type: ignore[no-untyped-def] super().__init__('git-vuln-finder', strict=strict, **kwargs) self._parameters = parameters self.generate_attributes() - def generate_attributes(self): + def generate_attributes(self) -> None: authored_date = self._sanitize_timestamp(self._parameters.pop('authored_date', None)) self._parameters['authored_date'] = authored_date committed_date = self._sanitize_timestamp(self._parameters.pop('committed_date', None)) diff --git a/pymisp/tools/load_warninglists.py b/pymisp/tools/load_warninglists.py index 8224a6c..feb5ea3 100644 --- a/pymisp/tools/load_warninglists.py +++ b/pymisp/tools/load_warninglists.py @@ -2,26 +2,29 @@ from __future__ import annotations +from ..api import PyMISP + try: - from pymispwarninglists import WarningLists # type: ignore + from pymispwarninglists import WarningLists, WarningList # type: ignore has_pymispwarninglists = True except ImportError: has_pymispwarninglists = False -def from_instance(pymisp_instance, slow_search=False): +def from_instance(pymisp_instance: PyMISP, slow_search: bool=False) -> WarningLists: """Load the warnindlist from an existing MISP instance :pymisp_instance: Already instantialized PyMISP instance.""" - warninglists_index = pymisp_instance.get_warninglists()['Warninglists'] + warninglists_index = pymisp_instance.warninglists(pythonify=True) all_warningslists = [] for warninglist in warninglists_index: - wl = pymisp_instance.get_warninglist(warninglist['Warninglist']['id'])['Warninglist'] - wl['list'] = wl.pop('WarninglistEntry') - all_warningslists.append(wl) + if isinstance(warninglist, WarningList): + wl = pymisp_instance.get_warninglist(warninglist['Warninglist']['id'])['Warninglist'] + wl['list'] = wl.pop('WarninglistEntry') + all_warningslists.append(wl) return WarningLists(slow_search, all_warningslists) -def from_package(slow_search=False): +def from_package(slow_search: bool=False) -> WarningLists: return WarningLists(slow_search) diff --git a/pymisp/tools/neo4j.py b/pymisp/tools/neo4j.py index ce479c1..7a71978 100644 --- a/pymisp/tools/neo4j.py +++ b/pymisp/tools/neo4j.py @@ -2,6 +2,7 @@ from __future__ import annotations import glob import os + from .. import MISPEvent try: @@ -13,23 +14,23 @@ except ImportError: class Neo4j(): - def __init__(self, host='localhost:7474', username='neo4j', password='neo4j'): + def __init__(self, host: str='localhost:7474', username: str='neo4j', password: str='neo4j') -> None: if not has_py2neo: raise Exception('py2neo is required, please install: pip install py2neo') authenticate(host, username, password) self.graph = Graph(f"http://{host}/db/data/") - def load_events_directory(self, directory): - self.events = [] + def load_events_directory(self, directory: str) -> None: + self.events: list[MISPEvent] = [] for path in glob.glob(os.path.join(directory, '*.json')): e = MISPEvent() e.load(path) self.import_event(e) - def del_all(self): + def del_all(self) -> None: self.graph.delete_all() - def import_event(self, event): + def import_event(self, event: MISPEvent) -> None: tx = self.graph.begin() event_node = Node('Event', uuid=event.uuid, name=event.info) # event_node['distribution'] = event.distribution diff --git a/pymisp/tools/sbsignatureobject.py b/pymisp/tools/sbsignatureobject.py index 35d8147..a7356a3 100644 --- a/pymisp/tools/sbsignatureobject.py +++ b/pymisp/tools/sbsignatureobject.py @@ -9,13 +9,13 @@ class SBSignatureObject(AbstractMISPObjectGenerator): ''' Sandbox Analyzer ''' - def __init__(self, software: str, report: list, **kwargs): + def __init__(self, software: str, report: list[tuple[str, str]], **kwargs) -> None: # type: ignore[no-untyped-def] super().__init__('sb-signature', **kwargs) self._software = software self._report = report self.generate_attributes() - def generate_attributes(self): + def generate_attributes(self) -> None: ''' Parse the report for relevant attributes ''' self.add_attribute("software", value=self._software) for (signature_name, description) in self._report: diff --git a/pymisp/tools/sshauthkeyobject.py b/pymisp/tools/sshauthkeyobject.py index d66cb1f..ce6c2fb 100644 --- a/pymisp/tools/sshauthkeyobject.py +++ b/pymisp/tools/sshauthkeyobject.py @@ -2,20 +2,21 @@ from __future__ import annotations +import logging + +from io import StringIO +from pathlib import Path + from ..exceptions import InvalidMISPObject from .abstractgenerator import AbstractMISPObjectGenerator -from io import StringIO -import logging -from typing import Optional, Union -from pathlib import Path logger = logging.getLogger('pymisp') class SSHAuthorizedKeysObject(AbstractMISPObjectGenerator): - def __init__(self, authorized_keys_path: Path | str | None = None, authorized_keys_pseudofile: StringIO | None = None, **kwargs): - # PY3 way: + def __init__(self, authorized_keys_path: Path | str | None = None, # type: ignore[no-untyped-def] + authorized_keys_pseudofile: StringIO | None = None, **kwargs): super().__init__('ssh-authorized-keys', **kwargs) if authorized_keys_path: with open(authorized_keys_path) as f: @@ -27,7 +28,7 @@ class SSHAuthorizedKeysObject(AbstractMISPObjectGenerator): self.__data = self.__pseudofile.getvalue() self.generate_attributes() - def generate_attributes(self): + def generate_attributes(self) -> None: for line in self.__pseudofile: if line.startswith('ssh') or line.startswith('ecdsa'): key = line.split(' ')[1] diff --git a/pymisp/tools/stix.py b/pymisp/tools/stix.py deleted file mode 100644 index 8f82459..0000000 --- a/pymisp/tools/stix.py +++ /dev/null @@ -1,35 +0,0 @@ -from __future__ import annotations - -try: - from misp_stix_converter.converters.buildMISPAttribute import buildEvent # type: ignore - from misp_stix_converter.converters import convert # type: ignore - from misp_stix_converter.converters.convert import MISPtoSTIX # type: ignore - has_misp_stix_converter = True -except ImportError: - has_misp_stix_converter = False - - -def load_stix(stix, distribution: int = 3, threat_level_id: int = 2, analysis: int = 0): - '''Returns a MISPEvent object from a STIX package''' - if not has_misp_stix_converter: - raise Exception('You need to install misp_stix_converter: pip install git+https://github.com/MISP/MISP-STIX-Converter.git') - stix = convert.load_stix(stix) - return buildEvent(stix, distribution=distribution, - threat_level_id=threat_level_id, analysis=analysis) - - -def make_stix_package(misp_event, to_json: bool = False, to_xml: bool = False): - '''Returns a STIXPackage from a MISPEvent. - - Optionally can return the package in json or xml. - - ''' - if not has_misp_stix_converter: - raise Exception('You need to install misp_stix_converter: pip install git+https://github.com/MISP/MISP-STIX-Converter.git') - package = MISPtoSTIX(misp_event) - if to_json: - return package.to_json() - elif to_xml: - return package.to_xml() - else: - return package diff --git a/pymisp/tools/update_objects.py b/pymisp/tools/update_objects.py index abe1835..7f1dd25 100644 --- a/pymisp/tools/update_objects.py +++ b/pymisp/tools/update_objects.py @@ -13,7 +13,7 @@ from ..abstract import resources_path static_repo = "https://github.com/MISP/misp-objects/archive/main.zip" -def update_objects(): +def update_objects() -> None: r = requests.get(static_repo) zipped_repo = BytesIO(r.content) diff --git a/pymisp/tools/urlobject.py b/pymisp/tools/urlobject.py index 956b0c9..3465541 100644 --- a/pymisp/tools/urlobject.py +++ b/pymisp/tools/urlobject.py @@ -2,10 +2,12 @@ from __future__ import annotations -from .abstractgenerator import AbstractMISPObjectGenerator import logging + from urllib.parse import unquote_plus +from .abstractgenerator import AbstractMISPObjectGenerator + try: from pyfaup.faup import Faup # type: ignore except (OSError, ImportError): @@ -18,13 +20,13 @@ faup = Faup() class URLObject(AbstractMISPObjectGenerator): - def __init__(self, url: str, generate_all=False, **kwargs): + def __init__(self, url: str, generate_all=False, **kwargs) -> None: # type: ignore[no-untyped-def] super().__init__('url', **kwargs) self._generate_all = True if generate_all is True else False faup.decode(unquote_plus(url)) self.generate_attributes() - def generate_attributes(self): + def generate_attributes(self) -> None: self.add_attribute('url', value=faup.url.decode()) if faup.get_host(): self.add_attribute('host', value=faup.get_host()) diff --git a/pymisp/tools/vehicleobject.py b/pymisp/tools/vehicleobject.py index da72f78..75c9a4a 100644 --- a/pymisp/tools/vehicleobject.py +++ b/pymisp/tools/vehicleobject.py @@ -5,6 +5,8 @@ from __future__ import annotations import requests import json +from typing import Any + from .abstractgenerator import AbstractMISPObjectGenerator # Original sourcecode: https://github.com/hayk57/MISP_registration_check @@ -13,14 +15,16 @@ from .abstractgenerator import AbstractMISPObjectGenerator class VehicleObject(AbstractMISPObjectGenerator): '''Vehicle object generator out of regcheck.org.uk''' - country_urls = { + country_urls: dict[str, str] = { 'fr': "http://www.regcheck.org.uk/api/reg.asmx/CheckFrance", 'es': "http://www.regcheck.org.uk/api/reg.asmx/CheckSpain", 'uk': "http://www.regcheck.org.uk/api/reg.asmx/Check" } - def __init__(self, country: str, registration: str, username: str, **kwargs): + def __init__(self, country: str, registration: str, username: str, **kwargs) -> None: # type: ignore[no-untyped-def] super().__init__('vehicle', **kwargs) + if country not in self.country_urls: + raise ValueError(f"Country {country} not supportet, must be one of {self.country_urls.keys()}") self._country = country self._registration = registration self._username = username @@ -28,10 +32,10 @@ class VehicleObject(AbstractMISPObjectGenerator): self.generate_attributes() @property - def report(self): + def report(self) -> dict[str, Any]: return self._report - def generate_attributes(self): + def generate_attributes(self) -> None: carDescription = self._report["Description"] carMake = self._report["CarMake"]["CurrentTextValue"] carModel = self._report["CarModel"]["CurrentTextValue"] @@ -67,14 +71,14 @@ class VehicleObject(AbstractMISPObjectGenerator): self.add_attribute('date-first-registration', type='text', value=firstRegistration) self.add_attribute('image-url', type='text', value=ImageUrl) - def _query(self): + def _query(self) -> dict[str, Any]: payload = f"RegistrationNumber={self._registration}&username={self._username}" headers = { 'Content-Type': "application/x-www-form-urlencoded", 'cache-control': "no-cache", } - response = requests.request("POST", self.country_urls.get(self._country), data=payload, headers=headers) + response = requests.request("POST", self.country_urls[self._country], data=payload, headers=headers) # FIXME: Clean that up. for item in response.text.split(""): if "" in item: diff --git a/pymisp/tools/vtreportobject.py b/pymisp/tools/vtreportobject.py index 1ad7654..47f917d 100644 --- a/pymisp/tools/vtreportobject.py +++ b/pymisp/tools/vtreportobject.py @@ -3,7 +3,7 @@ from __future__ import annotations import re -from typing import Optional +from typing import Any import requests try: @@ -25,7 +25,7 @@ class VTReportObject(AbstractMISPObjectGenerator): :indicator: IOC to search VirusTotal for ''' - def __init__(self, apikey: str, indicator: str, vt_proxies: dict | None = None, **kwargs): + def __init__(self, apikey: str, indicator: str, vt_proxies: dict[str, str] | None = None, **kwargs) -> None: # type: ignore[no-untyped-def] super().__init__('virustotal-report', **kwargs) indicator = indicator.strip() self._resource_type = self.__validate_resource(indicator) @@ -37,17 +37,17 @@ class VTReportObject(AbstractMISPObjectGenerator): error_msg = f"A valid indicator is required. (One of type url, md5, sha1, sha256). Received '{indicator}' instead" raise InvalidMISPObject(error_msg) - def get_report(self): + def get_report(self) -> dict[str, Any]: return self._report - def generate_attributes(self): + def generate_attributes(self) -> None: ''' Parse the VirusTotal report for relevant attributes ''' self.add_attribute("last-submission", value=self._report["scan_date"]) self.add_attribute("permalink", value=self._report["permalink"]) ratio = "{}/{}".format(self._report["positives"], self._report["total"]) self.add_attribute("detection-ratio", value=ratio) - def __validate_resource(self, ioc: str): + def __validate_resource(self, ioc: str) -> str | bool: ''' Validate the data type of an indicator. Domains and IP addresses aren't supported because @@ -63,7 +63,7 @@ class VTReportObject(AbstractMISPObjectGenerator): return "file" return False - def __query_virustotal(self, apikey: str, resource: str): + def __query_virustotal(self, apikey: str, resource: str) -> dict[str, Any]: ''' Query VirusTotal for information about an indicator diff --git a/tests/test_emailobject.py b/tests/test_emailobject.py index bd3ae93..01cb9d0 100644 --- a/tests/test_emailobject.py +++ b/tests/test_emailobject.py @@ -7,22 +7,26 @@ from email.message import EmailMessage from io import BytesIO from os import urandom from pathlib import Path -from typing import List +from typing import TypeVar, Type from zipfile import ZipFile from pymisp.tools import EMailObject from pymisp.exceptions import PyMISPNotImplementedYet, InvalidMISPObject +T = TypeVar('T', bound='TestEmailObject') + class TestEmailObject(unittest.TestCase): + eml_1: BytesIO + @classmethod - def setUpClass(cls): + def setUpClass(cls: type[T]) -> None: with ZipFile(Path("tests/email_testfiles/mail_1.eml.zip"), 'r') as myzip: with myzip.open('mail_1.eml', pwd=b'AVs are dumb') as myfile: cls.eml_1 = BytesIO(myfile.read()) - def test_mail_1(self): + def test_mail_1(self) -> None: email_object = EMailObject(pseudofile=self.eml_1) self.assertEqual(self._get_values(email_object, "subject")[0], "письмо уведом-е") self.assertEqual(self._get_values(email_object, "to")[0], "kinney@noth.com") @@ -39,7 +43,7 @@ class TestEmailObject(unittest.TestCase): self.assertIsInstance(file_name, str) self.assertIsInstance(file_content, BytesIO) - def test_mail_1_headers_only(self): + def test_mail_1_headers_only(self) -> None: email_object = EMailObject(Path("tests/email_testfiles/mail_1_headers_only.eml")) self.assertEqual(self._get_values(email_object, "subject")[0], "письмо уведом-е") self.assertEqual(self._get_values(email_object, "to")[0], "kinney@noth.com") @@ -50,7 +54,7 @@ class TestEmailObject(unittest.TestCase): self.assertIsInstance(email_object.email, EmailMessage) self.assertEqual(len(email_object.attachments), 0) - def test_mail_multiple_to(self): + def test_mail_multiple_to(self) -> None: email_object = EMailObject(Path("tests/email_testfiles/mail_multiple_to.eml")) to = self._get_values(email_object, "to") @@ -60,7 +64,7 @@ class TestEmailObject(unittest.TestCase): self.assertEqual(to[1], "jan.marek@example.com") self.assertEqual(to_display_name[1], "Marek, Jan") - def test_msg(self): + def test_msg(self) -> None: # Test result of eml converted to msg is the same eml_email_object = EMailObject(pseudofile=self.eml_1) email_object = EMailObject(Path("tests/email_testfiles/mail_1.msg")) @@ -83,7 +87,7 @@ class TestEmailObject(unittest.TestCase): self.assertEqual(self._get_values(email_object, "received-header-ip"), self._get_values(eml_email_object, "received-header-ip")) - def test_bom_encoded(self): + def test_bom_encoded(self) -> None: """Test utf-8-sig encoded email""" bom_email_object = EMailObject(Path("tests/email_testfiles/mail_1_bom.eml")) eml_email_object = EMailObject(pseudofile=self.eml_1) @@ -106,7 +110,7 @@ class TestEmailObject(unittest.TestCase): self.assertEqual(self._get_values(bom_email_object, "received-header-ip"), self._get_values(eml_email_object, "received-header-ip")) - def test_handling_of_various_email_types(self): + def test_handling_of_various_email_types(self) -> None: self._does_not_fail(Path("tests/email_testfiles/mail_2.eml"), "ensuring all headers work") self._does_not_fail(Path('tests/email_testfiles/mail_3.eml'), @@ -118,7 +122,7 @@ class TestEmailObject(unittest.TestCase): self._does_not_fail(Path('tests/email_testfiles/mail_5.msg'), "Check encapsulated HTML works") - def _does_not_fail(self, path, test_type="test"): + def _does_not_fail(self, path: Path, test_type: str="test") -> None: found_error = None try: EMailObject(path) @@ -130,7 +134,7 @@ class TestEmailObject(unittest.TestCase): path, test_type)) - def test_random_binary_blob(self): + def test_random_binary_blob(self) -> None: """Email parser fails correctly on random binary blob.""" random_data = urandom(1024) random_blob = BytesIO(random_data) @@ -145,8 +149,8 @@ class TestEmailObject(unittest.TestCase): broken_obj = EMailObject(pseudofile=random_blob) except Exception as _e: found_error = _e - if not isinstance(found_error, PyMISPNotImplementedYet): - self.fail("Expected PyMISPNotImplementedYet when EmailObject receives completely unknown binary input data in a pseudofile. But, did not get that exception.") + if not isinstance(found_error, InvalidMISPObject): + self.fail("Expected InvalidMISPObject when EmailObject receives completely unknown binary input data in a pseudofile. But, did not get that exception.") @staticmethod def _get_values(obj: EMailObject, relation: str) -> list[str]: diff --git a/tests/test_fileobject.py b/tests/test_fileobject.py index 6d4b5aa..1299b3a 100644 --- a/tests/test_fileobject.py +++ b/tests/test_fileobject.py @@ -9,7 +9,7 @@ import pathlib class TestFileObject(unittest.TestCase): - def test_mimeType(self): + def test_mimeType(self) -> None: file_object = FileObject(filepath=pathlib.Path(__file__)) attributes = json.loads(file_object.to_json())['Attribute'] mime = next(attr for attr in attributes if attr['object_relation'] == 'mimetype') diff --git a/tests/test_mispevent.py b/tests/test_mispevent.py index d0a3bbd..8c9564c 100644 --- a/tests/test_mispevent.py +++ b/tests/test_mispevent.py @@ -17,24 +17,24 @@ from pymisp.tools import GitVulnFinderObject class TestMISPEvent(unittest.TestCase): - def setUp(self): + def setUp(self) -> None: self.maxDiff = None self.mispevent = MISPEvent() - def init_event(self): + def init_event(self) -> None: self.mispevent.info = 'This is a test' self.mispevent.distribution = 1 self.mispevent.threat_level_id = 1 self.mispevent.analysis = 1 self.mispevent.set_date("2017-12-31") # test the set date method - def test_simple(self): + def test_simple(self) -> None: with open('tests/mispevent_testfiles/simple.json') as f: ref_json = json.load(f) del self.mispevent.uuid self.assertEqual(self.mispevent.to_json(sort_keys=True, indent=2), json.dumps(ref_json, sort_keys=True, indent=2)) - def test_event(self): + def test_event(self) -> None: self.init_event() self.mispevent.publish() with open('tests/mispevent_testfiles/event.json') as f: @@ -42,22 +42,22 @@ class TestMISPEvent(unittest.TestCase): del self.mispevent.uuid self.assertEqual(self.mispevent.to_json(sort_keys=True, indent=2), json.dumps(ref_json, sort_keys=True, indent=2)) - def test_loadfile(self): + def test_loadfile(self) -> None: self.mispevent.load_file('tests/mispevent_testfiles/event.json') with open('tests/mispevent_testfiles/event.json') as f: ref_json = json.load(f) del self.mispevent.uuid self.assertEqual(self.mispevent.to_json(sort_keys=True, indent=2), json.dumps(ref_json, sort_keys=True, indent=2)) - def test_loadfile_validate(self): + def test_loadfile_validate(self) -> None: misp_event = MISPEvent() misp_event.load_file('tests/mispevent_testfiles/event.json', validate=True) - def test_loadfile_validate_strict(self): + def test_loadfile_validate_strict(self) -> None: misp_event = MISPEvent(strict_validation=True) misp_event.load_file('tests/mispevent_testfiles/event.json', validate=True) - def test_event_tag(self): + def test_event_tag(self) -> None: self.init_event() self.mispevent.add_tag('bar') self.mispevent.add_tag(name='baz') @@ -69,7 +69,7 @@ class TestMISPEvent(unittest.TestCase): del self.mispevent.uuid self.assertEqual(self.mispevent.to_json(sort_keys=True, indent=2), json.dumps(ref_json, sort_keys=True, indent=2)) - def test_event_galaxy(self): + def test_event_galaxy(self) -> None: self.init_event() with open('tests/mispevent_testfiles/galaxy.json') as f: galaxy = json.load(f) @@ -78,11 +78,11 @@ class TestMISPEvent(unittest.TestCase): self.mispevent.add_galaxy(misp_galaxy) self.assertEqual(self.mispevent.galaxies[0].to_json(sort_keys=True, indent=2), json.dumps(galaxy, sort_keys=True, indent=2)) - def test_attribute(self): + def test_attribute(self) -> None: self.init_event() - a = self.mispevent.add_attribute('filename', 'bar.exe') + a: MISPAttribute = self.mispevent.add_attribute('filename', 'bar.exe') # type: ignore[assignment] del a.uuid - a = self.mispevent.add_attribute_tag('osint', 'bar.exe') + a = self.mispevent.add_attribute_tag('osint', 'bar.exe') # type: ignore[assignment] attr_tags = self.mispevent.get_attribute_tag('bar.exe') self.assertEqual(self.mispevent.attributes[0].tags[0].name, 'osint') self.assertEqual(attr_tags[0].name, 'osint') @@ -97,7 +97,7 @@ class TestMISPEvent(unittest.TestCase): ref_json = json.load(f) self.assertEqual(self.mispevent.to_json(sort_keys=True, indent=2), json.dumps(ref_json, sort_keys=True, indent=2)) - def test_attribute_galaxy(self): + def test_attribute_galaxy(self) -> None: self.init_event() with open('tests/mispevent_testfiles/galaxy.json') as f: galaxy = json.load(f) @@ -112,7 +112,7 @@ class TestMISPEvent(unittest.TestCase): json.dumps(galaxy, sort_keys=True, indent=2) ) - def test_to_dict_json_format(self): + def test_to_dict_json_format(self) -> None: misp_event = MISPEvent() av_signature_object = MISPObject("av-signature") av_signature_object.add_attribute("signature", "EICAR") @@ -121,19 +121,19 @@ class TestMISPEvent(unittest.TestCase): self.assertEqual(json.loads(misp_event.to_json()), misp_event.to_dict(json_format=True)) - def test_object_tag(self): + def test_object_tag(self) -> None: self.mispevent.add_object(name='file', strict=True) - a = self.mispevent.objects[0].add_attribute('filename', value='') + a: MISPAttribute = self.mispevent.objects[0].add_attribute('filename', value='') # type: ignore[assignment] self.assertEqual(a, None) - a = self.mispevent.objects[0].add_attribute('filename', value=None) + a = self.mispevent.objects[0].add_attribute('filename', value=None) # type: ignore[assignment] self.assertEqual(a, None) - a = self.mispevent.objects[0].add_attribute('filename', value='bar', Tag=[{'name': 'blah'}]) + a = self.mispevent.objects[0].add_attribute('filename', value='bar', Tag=[{'name': 'blah'}]) # type: ignore[assignment] del a.uuid self.assertEqual(self.mispevent.objects[0].attributes[0].tags[0].name, 'blah') self.assertTrue(self.mispevent.objects[0].has_attributes_by_relation(['filename'])) self.assertEqual(len(self.mispevent.objects[0].get_attributes_by_relation('filename')), 1) self.mispevent.add_object(name='url', strict=True) - a = self.mispevent.objects[1].add_attribute('url', value='https://www.circl.lu') + a = self.mispevent.objects[1].add_attribute('url', value='https://www.circl.lu') # type: ignore[assignment] del a.uuid self.mispevent.objects[0].uuid = 'a' self.mispevent.objects[1].uuid = 'b' @@ -146,16 +146,16 @@ class TestMISPEvent(unittest.TestCase): self.assertEqual(self.mispevent.to_json(sort_keys=True, indent=2), json.dumps(ref_json, sort_keys=True, indent=2)) @unittest.skip("Not supported on MISP: https://github.com/MISP/MISP/issues/2638 - https://github.com/MISP/PyMISP/issues/168") - def test_object_level_tag(self): + def test_object_level_tag(self) -> None: self.mispevent.add_object(name='file', strict=True) self.mispevent.objects[0].add_attribute('filename', value='bar') - self.mispevent.objects[0].add_tag('osint') + self.mispevent.objects[0].add_tag('osint') # type: ignore[attr-defined] self.mispevent.objects[0].uuid = 'a' with open('tests/mispevent_testfiles/event_obj_tag.json') as f: ref_json = json.load(f) self.assertEqual(self.mispevent.to_json(sort_keys=True, indent=2), json.dumps(ref_json, sort_keys=True, indent=2)) - def test_object_galaxy(self): + def test_object_galaxy(self) -> None: self.init_event() misp_object = MISPObject('github-user') misp_object.add_attribute('username', 'adulau') @@ -171,11 +171,11 @@ class TestMISPEvent(unittest.TestCase): json.dumps(galaxy, sort_keys=True, indent=2) ) - def test_malware(self): + def test_malware(self) -> None: with open('tests/mispevent_testfiles/simple.json', 'rb') as f: pseudofile = BytesIO(f.read()) self.init_event() - a = self.mispevent.add_attribute('malware-sample', 'bar.exe', data=pseudofile) + a: MISPAttribute = self.mispevent.add_attribute('malware-sample', 'bar.exe', data=pseudofile) # type: ignore[assignment] del a.uuid attribute = self.mispevent.attributes[0] self.assertEqual(attribute.malware_binary, pseudofile) @@ -184,40 +184,40 @@ class TestMISPEvent(unittest.TestCase): del self.mispevent.uuid self.assertEqual(self.mispevent.to_json(sort_keys=True, indent=2), json.dumps(ref_json, sort_keys=True, indent=2)) - def test_existing_malware(self): + def test_existing_malware(self) -> None: self.mispevent.load_file('tests/mispevent_testfiles/malware_exist.json') with open('tests/mispevent_testfiles/simple.json', 'rb') as f: pseudofile = BytesIO(f.read()) - self.assertEqual( - self.mispevent.objects[0].get_attributes_by_relation('malware-sample')[0].malware_binary.read(), - pseudofile.read()) + self.assertTrue(self.mispevent.objects[0].get_attributes_by_relation('malware-sample')[0].malware_binary) + if _mb := self.mispevent.objects[0].get_attributes_by_relation('malware-sample')[0].malware_binary: + self.assertEqual(_mb.read(), pseudofile.read()) - def test_sighting(self): + def test_sighting(self) -> None: sighting = MISPSighting() sighting.from_dict(value='1', type='bar', timestamp=11111111) with open('tests/mispevent_testfiles/sighting.json') as f: ref_json = json.load(f) self.assertEqual(sighting.to_json(sort_keys=True, indent=2), json.dumps(ref_json, sort_keys=True, indent=2)) - def test_existing_event(self): + def test_existing_event(self) -> None: self.mispevent.load_file('tests/mispevent_testfiles/existing_event.json') with open('tests/mispevent_testfiles/existing_event.json') as f: ref_json = json.load(f) self.assertEqual(self.mispevent.to_json(sort_keys=True, indent=2), json.dumps(ref_json, sort_keys=True, indent=2)) - def test_shadow_attributes_existing(self): + def test_shadow_attributes_existing(self) -> None: self.mispevent.load_file('tests/mispevent_testfiles/shadow.json') with open('tests/mispevent_testfiles/shadow.json') as f: ref_json = json.load(f) self.assertEqual(self.mispevent.to_json(sort_keys=True, indent=2), json.dumps(ref_json, sort_keys=True, indent=2)) @unittest.skip("Not supported on MISP.") - def test_shadow_attributes(self): + def test_shadow_attributes(self) -> None: self.init_event() p = self.mispevent.add_proposal(type='filename', value='baz.jpg') del p.uuid - a = self.mispevent.add_attribute('filename', 'bar.exe') + a: MISPAttribute = self.mispevent.add_attribute('filename', 'bar.exe') # type: ignore[assignment] del a.uuid p = self.mispevent.attributes[0].add_proposal(type='filename', value='bar.pdf') del p.uuid @@ -225,15 +225,15 @@ class TestMISPEvent(unittest.TestCase): ref_json = json.load(f) self.assertEqual(self.mispevent.to_json(sort_keys=True, indent=2), json.dumps(ref_json, sort_keys=True, indent=2)) - def test_default_attributes(self): + def test_default_attributes(self) -> None: self.mispevent.add_object(name='file', strict=True) - a = self.mispevent.objects[0].add_attribute('filename', value='bar', Tag=[{'name': 'blah'}]) + a: MISPAttribute = self.mispevent.objects[0].add_attribute('filename', value='bar', Tag=[{'name': 'blah'}]) # type: ignore[assignment] del a.uuid - a = self.mispevent.objects[0].add_attribute('pattern-in-file', value='baz') + a = self.mispevent.objects[0].add_attribute('pattern-in-file', value='baz') # type: ignore[assignment] self.assertEqual(a.category, 'Artifacts dropped') del a.uuid self.mispevent.add_object(name='file', strict=False, default_attributes_parameters=self.mispevent.objects[0].attributes[0]) - a = self.mispevent.objects[1].add_attribute('filename', value='baz') + a = self.mispevent.objects[1].add_attribute('filename', value='baz') # type: ignore[assignment] del a.uuid self.mispevent.objects[0].uuid = 'a' self.mispevent.objects[1].uuid = 'b' @@ -242,16 +242,16 @@ class TestMISPEvent(unittest.TestCase): del self.mispevent.uuid self.assertEqual(self.mispevent.to_json(sort_keys=True, indent=2), json.dumps(ref_json, sort_keys=True, indent=2)) - def test_obj_default_values(self): + def test_obj_default_values(self) -> None: self.init_event() self.mispevent.add_object(name='whois', strict=True) - a = self.mispevent.objects[0].add_attribute('registrar', value='registar.example.com') + a: MISPAttribute = self.mispevent.objects[0].add_attribute('registrar', value='registar.example.com') # type: ignore[assignment] del a.uuid - a = self.mispevent.objects[0].add_attribute('domain', value='domain.example.com') + a = self.mispevent.objects[0].add_attribute('domain', value='domain.example.com') # type: ignore[assignment] del a.uuid - a = self.mispevent.objects[0].add_attribute('nameserver', value='ns1.example.com') + a = self.mispevent.objects[0].add_attribute('nameserver', value='ns1.example.com') # type: ignore[assignment] del a.uuid - a = self.mispevent.objects[0].add_attribute('nameserver', value='ns2.example.com', disable_correlation=False, to_ids=True, category='External analysis') + a = self.mispevent.objects[0].add_attribute('nameserver', value='ns2.example.com', disable_correlation=False, to_ids=True, category='External analysis') # type: ignore[assignment] del a.uuid self.mispevent.objects[0].uuid = 'a' with open('tests/mispevent_testfiles/def_param.json') as f: @@ -259,7 +259,7 @@ class TestMISPEvent(unittest.TestCase): del self.mispevent.uuid self.assertEqual(self.mispevent.to_json(sort_keys=True, indent=2), json.dumps(ref_json, sort_keys=True, indent=2)) - def test_obj_references_export(self): + def test_obj_references_export(self) -> None: self.init_event() obj1 = MISPObject(name="file") obj2 = MISPObject(name="url", standalone=False) @@ -272,29 +272,29 @@ class TestMISPEvent(unittest.TestCase): self.assertTrue("ObjectReference" in obj1.jsonable()) self.assertFalse("ObjectReference" in obj2.jsonable()) - def test_event_not_edited(self): + def test_event_not_edited(self) -> None: self.mispevent.load_file('tests/mispevent_testfiles/existing_event.json') self.assertFalse(self.mispevent.edited) - def test_event_edited(self): + def test_event_edited(self) -> None: self.mispevent.load_file('tests/mispevent_testfiles/existing_event.json') self.mispevent.info = 'blah' self.assertTrue(self.mispevent.edited) - def test_event_tag_edited(self): + def test_event_tag_edited(self) -> None: self.mispevent.load_file('tests/mispevent_testfiles/existing_event.json') self.assertFalse(self.mispevent.edited) self.mispevent.add_tag('foo') self.assertTrue(self.mispevent.edited) - def test_event_attribute_edited(self): + def test_event_attribute_edited(self) -> None: self.mispevent.load_file('tests/mispevent_testfiles/existing_event.json') self.mispevent.attributes[0].value = 'blah' self.assertTrue(self.mispevent.attributes[0].edited) self.assertFalse(self.mispevent.attributes[1].edited) self.assertTrue(self.mispevent.edited) - def test_event_attribute_tag_edited(self): + def test_event_attribute_tag_edited(self) -> None: self.mispevent.load_file('tests/mispevent_testfiles/existing_event.json') self.assertFalse(self.mispevent.edited) self.mispevent.attributes[0].tags[0].name = 'blah' @@ -303,14 +303,14 @@ class TestMISPEvent(unittest.TestCase): self.assertTrue(self.mispevent.attributes[0].edited) self.assertTrue(self.mispevent.edited) - def test_event_attribute_tag_edited_second(self): + def test_event_attribute_tag_edited_second(self) -> None: self.mispevent.load_file('tests/mispevent_testfiles/existing_event.json') self.assertFalse(self.mispevent.edited) self.mispevent.attributes[0].add_tag(name='blah') self.assertTrue(self.mispevent.attributes[0].edited) self.assertTrue(self.mispevent.edited) - def test_event_object_edited(self): + def test_event_object_edited(self) -> None: self.mispevent.load_file('tests/mispevent_testfiles/existing_event.json') self.assertFalse(self.mispevent.edited) self.mispevent.objects[0].comment = 'blah' @@ -318,7 +318,7 @@ class TestMISPEvent(unittest.TestCase): self.assertFalse(self.mispevent.objects[1].edited) self.assertTrue(self.mispevent.edited) - def test_event_object_attribute_edited(self): + def test_event_object_attribute_edited(self) -> None: self.mispevent.load_file('tests/mispevent_testfiles/existing_event.json') self.assertFalse(self.mispevent.edited) self.mispevent.objects[0].attributes[0].comment = 'blah' @@ -326,7 +326,7 @@ class TestMISPEvent(unittest.TestCase): self.assertTrue(self.mispevent.objects[0].edited) self.assertTrue(self.mispevent.edited) - def test_event_object_attribute_edited_tag(self): + def test_event_object_attribute_edited_tag(self) -> None: self.mispevent.load_file('tests/mispevent_testfiles/existing_event.json') self.assertFalse(self.mispevent.edited) self.mispevent.objects[0].attributes[0].add_tag('blah') @@ -337,12 +337,12 @@ class TestMISPEvent(unittest.TestCase): ref_json = json.load(f) self.assertEqual(self.mispevent.to_json(sort_keys=True, indent=2), json.dumps(ref_json, sort_keys=True, indent=2)) - def test_obj_by_id(self): + def test_obj_by_id(self) -> None: self.mispevent.load_file('tests/mispevent_testfiles/existing_event.json') misp_obj = self.mispevent.get_object_by_id(1556) self.assertEqual(misp_obj.uuid, '5a3cd604-e11c-4de5-bbbf-c170950d210f') - def test_userdefined_object_custom_template(self): + def test_userdefined_object_custom_template(self) -> None: self.init_event() with open('tests/mispevent_testfiles/test_object_template/definition.json') as f: template = json.load(f) @@ -353,16 +353,16 @@ class TestMISPEvent(unittest.TestCase): self.mispevent.to_json(sort_keys=True, indent=2) self.assertEqual(e.exception.message, '{\'member3\'} are required.') - a = self.mispevent.objects[0].add_attribute('member3', value='foo') + a: MISPAttribute = self.mispevent.objects[0].add_attribute('member3', value='foo') # type: ignore[assignment] del a.uuid with self.assertRaises(InvalidMISPObject) as e: # Fail on requiredOneOf self.mispevent.to_json(sort_keys=True, indent=2) self.assertEqual(e.exception.message, 'At least one of the following attributes is required: member1, member2') - a = self.mispevent.objects[0].add_attribute('member1', value='bar') + a = self.mispevent.objects[0].add_attribute('member1', value='bar') # type: ignore[assignment] del a.uuid - a = self.mispevent.objects[0].add_attribute('member1', value='baz') + a = self.mispevent.objects[0].add_attribute('member1', value='baz') # type: ignore[assignment] del a.uuid with self.assertRaises(InvalidMISPObject) as e: # member1 is not a multiple @@ -376,7 +376,7 @@ class TestMISPEvent(unittest.TestCase): del self.mispevent.uuid self.assertEqual(self.mispevent.to_json(sort_keys=True, indent=2), json.dumps(ref_json, sort_keys=True, indent=2)) - def test_userdefined_object_custom_dir(self): + def test_userdefined_object_custom_dir(self) -> None: self.init_event() self.mispevent.add_object(name='test_object_template', strict=True, misp_objects_path_custom='tests/mispevent_testfiles') with self.assertRaises(InvalidMISPObject) as e: @@ -384,16 +384,16 @@ class TestMISPEvent(unittest.TestCase): self.mispevent.to_json(sort_keys=True, indent=2) self.assertEqual(e.exception.message, '{\'member3\'} are required.') - a = self.mispevent.objects[0].add_attribute('member3', value='foo') + a: MISPAttribute = self.mispevent.objects[0].add_attribute('member3', value='foo') # type: ignore[assignment] del a.uuid with self.assertRaises(InvalidMISPObject) as e: # Fail on requiredOneOf self.mispevent.to_json(sort_keys=True, indent=2) self.assertEqual(e.exception.message, 'At least one of the following attributes is required: member1, member2') - a = self.mispevent.objects[0].add_attribute('member1', value='bar') + a = self.mispevent.objects[0].add_attribute('member1', value='bar') # type: ignore[assignment] del a.uuid - a = self.mispevent.objects[0].add_attribute('member1', value='baz') + a = self.mispevent.objects[0].add_attribute('member1', value='baz') # type: ignore[assignment] del a.uuid with self.assertRaises(InvalidMISPObject) as e: # member1 is not a multiple @@ -407,10 +407,10 @@ class TestMISPEvent(unittest.TestCase): del self.mispevent.uuid self.assertEqual(self.mispevent.to_json(sort_keys=True, indent=2), json.dumps(ref_json, sort_keys=True, indent=2)) - def test_first_last_seen(self): + def test_first_last_seen(self) -> None: me = MISPEvent() me.info = 'Test First and Last Seen' - me.date = '2020.01.12' + me.date = '2020.01.12' # type: ignore[assignment] self.assertEqual(me.date.day, 12) me.add_attribute('ip-dst', '8.8.8.8', first_seen='06-21-1998', last_seen=1580213607.469571) self.assertEqual(me.attributes[0].first_seen.year, 1998) @@ -418,11 +418,11 @@ class TestMISPEvent(unittest.TestCase): now = datetime.now().astimezone() me.attributes[0].last_seen = now today = date.today() - me.attributes[0].first_seen = today + me.attributes[0].first_seen = today # type: ignore[assignment] self.assertEqual(me.attributes[0].first_seen.year, today.year) self.assertEqual(me.attributes[0].last_seen, now) - def test_feed(self): + def test_feed(self) -> None: me = MISPEvent() me.info = 'Test feed' org = MISPOrganisation() @@ -440,7 +440,7 @@ class TestMISPEvent(unittest.TestCase): self.assertEqual(feed['Event']['_manifest'][me.uuid]['info'], 'Test feed') self.assertEqual(len(feed['Event']['Object'][0]['Attribute']), 2) - def test_object_templates(self): + def test_object_templates(self) -> None: me = MISPEvent() for template in glob.glob(str(me.misp_objects_path / '*' / 'definition.json')): with open(template) as f: @@ -459,7 +459,7 @@ class TestMISPEvent(unittest.TestCase): subset = set(entry['categories']).issubset(me.describe_types['categories']) self.assertTrue(subset, f'{t_json["name"]} - {obj_relation}') - def test_git_vuln_finder(self): + def test_git_vuln_finder(self) -> None: with open('tests/git-vuln-finder-quagga.json') as f: dump = json.load(f) diff --git a/tests/testlive_comprehensive.py b/tests/testlive_comprehensive.py index 852d7a3..e2b7198 100644 --- a/tests/testlive_comprehensive.py +++ b/tests/testlive_comprehensive.py @@ -2,35 +2,31 @@ from __future__ import annotations +import hashlib +import json +import logging import os -import sys - +import time import unittest -from pymisp.tools import make_binary_objects from datetime import datetime, timedelta, date, timezone from io import BytesIO -import json from pathlib import Path -import hashlib - -import urllib3 -import time +from typing import TypeVar, Type, Any from uuid import uuid4 -import email - -from collections import defaultdict - -import logging -logging.disable(logging.CRITICAL) -logger = logging.getLogger('pymisp') +import urllib3 +from pymisp.tools import make_binary_objects try: - from pymisp import register_user, PyMISP, MISPEvent, MISPOrganisation, MISPUser, Distribution, ThreatLevel, Analysis, MISPObject, MISPAttribute, MISPSighting, MISPShadowAttribute, MISPTag, MISPSharingGroup, MISPFeed, MISPServer, MISPUserSetting, MISPEventBlocklist, MISPEventReport, MISPCorrelationExclusion, MISPGalaxyCluster + from pymisp import (register_user, PyMISP, MISPEvent, MISPOrganisation, + MISPUser, Distribution, ThreatLevel, Analysis, MISPObject, + MISPAttribute, MISPSighting, MISPShadowAttribute, MISPTag, + MISPSharingGroup, MISPFeed, MISPServer, MISPUserSetting, + MISPEventReport, MISPCorrelationExclusion, MISPGalaxyCluster, + MISPGalaxy, MISPOrganisationBlocklist, MISPEventBlocklist) from pymisp.tools import CSVLoader, DomainIPObject, ASNObject, GenericObjectGenerator - from pymisp.exceptions import MISPServerError except ImportError: raise @@ -43,6 +39,8 @@ except ImportError as e: key = 'sL9hrjIyY405RyGQHLx5DoCAM92BNmmGa8P4ck1E' verifycert = False +logging.disable(logging.CRITICAL) +logger = logging.getLogger('pymisp') urllib3.disable_warnings() @@ -56,11 +54,23 @@ if not test_file_path.exists(): print('The test files are missing, pulling it.') os.system('git clone https://github.com/viper-framework/viper-test-files.git tests/viper-test-files') +T = TypeVar('T', bound='TestComprehensive') + class TestComprehensive(unittest.TestCase): + admin_misp_connector: PyMISP + user_misp_connector: PyMISP + test_usr: MISPUser + test_pub: MISPUser + test_org: MISPOrganisation + test_org_delegate: MISPOrganisation + delegate_user_misp_connector: PyMISP + pub_misp_connector: PyMISP + test_usr_delegate: MISPUser + @classmethod - def setUpClass(cls): + def setUpClass(cls: type[T]) -> None: cls.maxDiff = None # Connect as admin cls.admin_misp_connector = PyMISP(url, key, verifycert, debug=False) @@ -72,18 +82,18 @@ class TestComprehensive(unittest.TestCase): # Creates an org organisation = MISPOrganisation() organisation.name = 'Test Org' - cls.test_org = cls.admin_misp_connector.add_organisation(organisation, pythonify=True) + cls.test_org = cls.admin_misp_connector.add_organisation(organisation, pythonify=True) # type: ignore[assignment] # Create an org to delegate to organisation = MISPOrganisation() organisation.name = 'Test Org - delegate' - cls.test_org_delegate = cls.admin_misp_connector.add_organisation(organisation, pythonify=True) + cls.test_org_delegate = cls.admin_misp_connector.add_organisation(organisation, pythonify=True) # type: ignore[assignment] # Set the refault role (id 3 on the VM) cls.admin_misp_connector.set_default_role(3) # Creates a user user = MISPUser() user.email = 'testusr@user.local' user.org_id = cls.test_org.id - cls.test_usr = cls.admin_misp_connector.add_user(user, pythonify=True) + cls.test_usr = cls.admin_misp_connector.add_user(user, pythonify=True) # type: ignore[assignment] cls.user_misp_connector = PyMISP(url, cls.test_usr.authkey, verifycert, debug=True) cls.user_misp_connector.toggle_global_pythonify() # Creates a publisher @@ -91,14 +101,14 @@ class TestComprehensive(unittest.TestCase): user.email = 'testpub@user.local' user.org_id = cls.test_org.id user.role_id = 4 - cls.test_pub = cls.admin_misp_connector.add_user(user, pythonify=True) + cls.test_pub = cls.admin_misp_connector.add_user(user, pythonify=True) # type: ignore[assignment] cls.pub_misp_connector = PyMISP(url, cls.test_pub.authkey, verifycert) # Creates a user that can accept a delegation request user = MISPUser() user.email = 'testusr@delegate.recipient.local' user.org_id = cls.test_org_delegate.id user.role_id = 2 - cls.test_usr_delegate = cls.admin_misp_connector.add_user(user, pythonify=True) + cls.test_usr_delegate = cls.admin_misp_connector.add_user(user, pythonify=True) # type: ignore[assignment] cls.delegate_user_misp_connector = PyMISP(url, cls.test_usr_delegate.authkey, verifycert, debug=False) cls.delegate_user_misp_connector.toggle_global_pythonify() if not fast_mode: @@ -111,7 +121,7 @@ class TestComprehensive(unittest.TestCase): cls.admin_misp_connector.load_default_feeds() @classmethod - def tearDownClass(cls): + def tearDownClass(cls) -> None: # Delete publisher cls.admin_misp_connector.delete_user(cls.test_pub) # Delete user @@ -121,16 +131,16 @@ class TestComprehensive(unittest.TestCase): cls.admin_misp_connector.delete_organisation(cls.test_org) cls.admin_misp_connector.delete_organisation(cls.test_org_delegate) - def create_simple_event(self, force_timestamps=False): + def create_simple_event(self, force_timestamps: bool=False) -> MISPEvent: mispevent = MISPEvent(force_timestamps=force_timestamps) mispevent.info = 'This is a super simple test' mispevent.distribution = Distribution.your_organisation_only - mispevent.threat_level_id = ThreatLevel.low - mispevent.analysis = Analysis.completed + mispevent.threat_level_id = int(ThreatLevel.low) + mispevent.analysis = int(Analysis.completed) mispevent.add_attribute('text', str(uuid4())) return mispevent - def environment(self): + def environment(self) -> tuple[MISPEvent, MISPEvent, MISPEvent]: first_event = MISPEvent() first_event.info = 'First event - org only - low - completed' first_event.distribution = Distribution.your_organisation_only @@ -172,13 +182,13 @@ class TestComprehensive(unittest.TestCase): # Create first and third event as admin # usr won't be able to see the first one - first = self.admin_misp_connector.add_event(first_event, pythonify=True) - third = self.admin_misp_connector.add_event(third_event, pythonify=True) + first: MISPEvent = self.admin_misp_connector.add_event(first_event, pythonify=True) # type: ignore[assignment] + third: MISPEvent = self.admin_misp_connector.add_event(third_event, pythonify=True) # type: ignore[assignment] # Create second event as user - second = self.user_misp_connector.add_event(second_event) + second: MISPEvent = self.user_misp_connector.add_event(second_event) # type: ignore[assignment] return first, second, third - def test_server_settings(self): + def test_server_settings(self) -> None: settings = self.admin_misp_connector.server_settings() for final_setting in settings['finalSettings']: if final_setting['setting'] == 'MISP.max_correlations_per_event': @@ -203,7 +213,7 @@ class TestComprehensive(unittest.TestCase): setting = self.admin_misp_connector.get_server_setting('MISP.live') self.assertTrue(setting['value']) - def test_search_value_event(self): + def test_search_value_event(self) -> None: '''Search a value on the event controller * Test ACL admin user vs normal user in an other org * Make sure we have one match @@ -211,17 +221,17 @@ class TestComprehensive(unittest.TestCase): try: first, second, third = self.environment() # Search as admin - events = self.admin_misp_connector.search(value=first.attributes[0].value, pythonify=True) + events: list[MISPEvent] = self.admin_misp_connector.search(value=first.attributes[0].value, pythonify=True) # type: ignore[assignment] self.assertEqual(len(events), 2) for e in events: self.assertIn(e.id, [first.id, second.id]) # Search as user - events = self.user_misp_connector.search(value=first.attributes[0].value) + events = self.user_misp_connector.search(value=first.attributes[0].value) # type: ignore[assignment] self.assertEqual(len(events), 1) for e in events: self.assertIn(e.id, [second.id]) # Non-existing value - events = self.user_misp_connector.search(value=str(uuid4())) + events = self.user_misp_connector.search(value=str(uuid4())) # type: ignore[assignment] self.assertEqual(events, []) finally: # Delete events @@ -229,37 +239,37 @@ class TestComprehensive(unittest.TestCase): self.admin_misp_connector.delete_event(second) self.admin_misp_connector.delete_event(third) - def test_search_value_attribute(self): + def test_search_value_attribute(self) -> None: '''Search value in attributes controller''' try: first, second, third = self.environment() # Search as admin - attributes = self.admin_misp_connector.search(controller='attributes', value=first.attributes[0].value, pythonify=True) + attributes: list[MISPAttribute] = self.admin_misp_connector.search(controller='attributes', value=first.attributes[0].value, pythonify=True) # type: ignore[assignment] self.assertEqual(len(attributes), 2) for a in attributes: self.assertIn(a.event_id, [first.id, second.id]) # Search as user - attributes = self.user_misp_connector.search(controller='attributes', value=first.attributes[0].value) + attributes = self.user_misp_connector.search(controller='attributes', value=first.attributes[0].value) # type: ignore[assignment] self.assertEqual(len(attributes), 1) for a in attributes: self.assertIn(a.event_id, [second.id]) # Non-existing value - attributes = self.user_misp_connector.search(controller='attributes', value=str(uuid4())) + attributes = self.user_misp_connector.search(controller='attributes', value=str(uuid4())) # type: ignore[assignment] self.assertEqual(attributes, []) # Include context - search as user (can only see one event) - attributes = self.user_misp_connector.search(controller='attributes', value=first.attributes[0].value, include_context=True, pythonify=True) + attributes = self.user_misp_connector.search(controller='attributes', value=first.attributes[0].value, include_context=True, pythonify=True) # type: ignore[assignment] self.assertTrue(isinstance(attributes[0].Event, MISPEvent)) self.assertEqual(attributes[0].Event.uuid, second.uuid) # Include context - search as admin (can see both event) - attributes = self.admin_misp_connector.search(controller='attributes', value=first.attributes[0].value, include_context=True, pythonify=True) + attributes = self.admin_misp_connector.search(controller='attributes', value=first.attributes[0].value, include_context=True, pythonify=True) # type: ignore[assignment] self.assertTrue(isinstance(attributes[0].Event, MISPEvent)) self.assertEqual(attributes[0].Event.uuid, first.uuid) self.assertEqual(attributes[1].Event.uuid, second.uuid) # Include correlations - search as admin (can see both event) - attributes = self.admin_misp_connector.search(controller='attributes', value=first.attributes[0].value, include_correlations=True, pythonify=True) + attributes = self.admin_misp_connector.search(controller='attributes', value=first.attributes[0].value, include_correlations=True, pythonify=True) # type: ignore[assignment] self.assertTrue(isinstance(attributes[0].Event, MISPEvent)) self.assertEqual(attributes[0].Event.uuid, first.uuid) self.assertEqual(attributes[1].Event.uuid, second.uuid) @@ -267,8 +277,9 @@ class TestComprehensive(unittest.TestCase): self.assertEqual(attributes[1].RelatedAttribute[0].Event.uuid, first.uuid) # Include sightings - search as admin (can see both event) - self.admin_misp_connector.add_sighting({'value': first.attributes[0].value}) - attributes = self.admin_misp_connector.search(controller='attributes', value=first.attributes[0].value, include_sightings=True, pythonify=True) + s: dict[str, Any] = {'value': first.attributes[0].value} + self.admin_misp_connector.add_sighting(s) + attributes = self.admin_misp_connector.search(controller='attributes', value=first.attributes[0].value, include_sightings=True, pythonify=True) # type: ignore[assignment] self.assertTrue(isinstance(attributes[0].Event, MISPEvent)) self.assertEqual(attributes[0].Event.uuid, first.uuid) self.assertEqual(attributes[1].Event.uuid, second.uuid) @@ -280,17 +291,21 @@ class TestComprehensive(unittest.TestCase): self.admin_misp_connector.delete_event(second) self.admin_misp_connector.delete_event(third) - def test_search_type_event(self): + def test_search_type_event(self) -> None: '''Search multiple events, search events containing attributes with specific types''' try: first, second, third = self.environment() # Search as admin - events = self.admin_misp_connector.search(timestamp=first.timestamp.timestamp(), pythonify=True) + if isinstance(first.timestamp, datetime): + ts = first.timestamp.timestamp() + else: + ts = first.timestamp + events: list[MISPEvent] = self.admin_misp_connector.search(timestamp=ts, pythonify=True) # type: ignore[assignment] self.assertEqual(len(events), 3) for e in events: self.assertIn(e.id, [first.id, second.id, third.id]) attributes_types_search = self.admin_misp_connector.build_complex_query(or_parameters=['ip-src', 'ip-dst']) - events = self.admin_misp_connector.search(timestamp=first.timestamp.timestamp(), + events = self.admin_misp_connector.search(timestamp=ts, # type: ignore[assignment,type-var] type_attribute=attributes_types_search, pythonify=True) self.assertEqual(len(events), 2) for e in events: @@ -301,28 +316,32 @@ class TestComprehensive(unittest.TestCase): self.admin_misp_connector.delete_event(second) self.admin_misp_connector.delete_event(third) - def test_search_index(self): + def test_search_index(self) -> None: try: first, second, third = self.environment() # Search as admin - events = self.admin_misp_connector.search_index(timestamp=first.timestamp.timestamp(), pythonify=True) + if isinstance(first.timestamp, datetime): + ts = first.timestamp.timestamp() + else: + ts = first.timestamp + events: MISPEvent = self.admin_misp_connector.search_index(timestamp=ts, pythonify=True) # type: ignore[assignment] self.assertEqual(len(events), 3) for e in events: self.assertIn(e.id, [first.id, second.id, third.id]) # Test limit and pagination - event_one = self.admin_misp_connector.search_index(timestamp=first.timestamp.timestamp(), limit=1, page=1, pythonify=True)[0] - event_two = self.admin_misp_connector.search_index(timestamp=first.timestamp.timestamp(), limit=1, page=2, pythonify=True)[0] + event_one: MISPEvent = self.admin_misp_connector.search_index(timestamp=ts, limit=1, page=1, pythonify=True)[0] # type: ignore[index,assignment] + event_two: MISPEvent = self.admin_misp_connector.search_index(timestamp=ts, limit=1, page=2, pythonify=True)[0] # type: ignore[index,assignment] self.assertTrue(event_one.id != event_two.id) two_events = self.admin_misp_connector.search_index(limit=2) self.assertTrue(len(two_events), 2) # Test ordering by the Info field. Can't use timestamp as each will likely have the same - event = self.admin_misp_connector.search_index(timestamp=first.timestamp.timestamp(), sort="info", desc=True, limit=1, pythonify=True)[0] + event: MISPEvent = self.admin_misp_connector.search_index(timestamp=ts, sort="info", desc=True, limit=1, pythonify=True)[0] # type: ignore[index,assignment] # First|Second|*Third* event self.assertEqual(event.id, third.id) # *First*|Second|Third event - event = self.admin_misp_connector.search_index(timestamp=first.timestamp.timestamp(), sort="info", desc=False, limit=1, pythonify=True)[0] + event = self.admin_misp_connector.search_index(timestamp=ts, sort="info", desc=False, limit=1, pythonify=True)[0] # type: ignore[index,assignment] self.assertEqual(event.id, first.id) finally: # Delete event @@ -330,7 +349,7 @@ class TestComprehensive(unittest.TestCase): self.admin_misp_connector.delete_event(second) self.admin_misp_connector.delete_event(third) - def test_search_objects(self): + def test_search_objects(self) -> None: '''Search for objects''' try: first = self.create_simple_event() @@ -348,7 +367,7 @@ class TestComprehensive(unittest.TestCase): # Delete event self.admin_misp_connector.delete_event(first) - def test_search_type_attribute(self): + def test_search_type_attribute(self) -> None: '''Search multiple attributes, search attributes with specific types''' try: first, second, third = self.environment() @@ -372,7 +391,7 @@ class TestComprehensive(unittest.TestCase): self.admin_misp_connector.delete_event(second) self.admin_misp_connector.delete_event(third) - def test_search_tag_event(self): + def test_search_tag_event(self) -> None: '''Search Tags at events level''' try: first, second, third = self.environment() @@ -406,7 +425,7 @@ class TestComprehensive(unittest.TestCase): self.admin_misp_connector.delete_event(second) self.admin_misp_connector.delete_event(third) - def test_search_tag_attribute(self): + def test_search_tag_attribute(self) -> None: '''Search Tags at attributes level''' try: first, second, third = self.environment() @@ -433,7 +452,7 @@ class TestComprehensive(unittest.TestCase): self.admin_misp_connector.delete_event(second) self.admin_misp_connector.delete_event(third) - def test_search_tag_advanced_event(self): + def test_search_tag_advanced_event(self) -> None: '''Advanced search Tags at events level''' try: first, second, third = self.environment() @@ -463,7 +482,7 @@ class TestComprehensive(unittest.TestCase): self.admin_misp_connector.delete_event(second) self.admin_misp_connector.delete_event(third) - def test_search_tag_advanced_attributes(self): + def test_search_tag_advanced_attributes(self) -> None: '''Advanced search Tags at attributes level''' try: first, second, third = self.environment() @@ -482,7 +501,7 @@ class TestComprehensive(unittest.TestCase): self.admin_misp_connector.delete_event(second) self.admin_misp_connector.delete_event(third) - def test_search_timestamp_event(self): + def test_search_timestamp_event(self) -> None: '''Search specific update timestamps at events level''' # Creating event 1 - timestamp 5 min ago first = self.create_simple_event(force_timestamps=True) @@ -518,7 +537,7 @@ class TestComprehensive(unittest.TestCase): self.admin_misp_connector.delete_event(first) self.admin_misp_connector.delete_event(second) - def test_search_timestamp_attribute(self): + def test_search_timestamp_attribute(self) -> None: '''Search specific update timestamps at attributes level''' # Creating event 1 - timestamp 5 min ago first = self.create_simple_event(force_timestamps=True) @@ -556,7 +575,7 @@ class TestComprehensive(unittest.TestCase): self.admin_misp_connector.delete_event(first) self.admin_misp_connector.delete_event(second) - def test_user_perms(self): + def test_user_perms(self) -> None: '''Test publish rights''' try: first = self.create_simple_event() @@ -572,7 +591,7 @@ class TestComprehensive(unittest.TestCase): # Delete event self.admin_misp_connector.delete_event(first) - def test_delete_with_update(self): + def test_delete_with_update(self) -> None: try: first = self.create_simple_event() obj = MISPObject('file') @@ -597,14 +616,14 @@ class TestComprehensive(unittest.TestCase): # Delete event self.admin_misp_connector.delete_event(first) - def test_get_non_exists_event(self): + def test_get_non_exists_event(self) -> None: event = self.user_misp_connector.get_event(0) # non exists id self.assertEqual(event['errors'][0], 404) event = self.user_misp_connector.get_event("ab2b6e28-fda5-4282-bf60-22b81de77851") # non exists uuid self.assertEqual(event['errors'][0], 404) - def test_delete_by_uuid(self): + def test_delete_by_uuid(self) -> None: try: first = self.create_simple_event() obj = MISPObject('file') @@ -641,7 +660,7 @@ class TestComprehensive(unittest.TestCase): # Delete event self.admin_misp_connector.delete_event(first) - def test_search_publish_timestamp(self): + def test_search_publish_timestamp(self) -> None: '''Search for a specific publication timestamp, an interval, and invalid values.''' # Creating event 1 first = self.create_simple_event() @@ -680,7 +699,7 @@ class TestComprehensive(unittest.TestCase): self.admin_misp_connector.delete_event(first) self.admin_misp_connector.delete_event(second) - def test_search_decay(self): + def test_search_decay(self) -> None: # Creating event 1 first = self.create_simple_event() first.add_attribute('ip-dst', '8.8.8.8') @@ -705,7 +724,7 @@ class TestComprehensive(unittest.TestCase): # Delete event self.admin_misp_connector.delete_event(first) - def test_default_distribution(self): + def test_default_distribution(self) -> None: '''The default distributions on the VM are This community only for the events and Inherit from event for attr/obj)''' first = self.create_simple_event() del first.distribution @@ -747,7 +766,7 @@ class TestComprehensive(unittest.TestCase): # Delete event self.admin_misp_connector.delete_event(first) - def test_exists(self): + def test_exists(self) -> None: """Check event, attribute and object existence""" event = self.create_simple_event() misp_object = MISPObject('domain-ip') @@ -784,7 +803,7 @@ class TestComprehensive(unittest.TestCase): self.assertFalse(self.user_misp_connector.object_exists(misp_object)) self.assertFalse(self.user_misp_connector.object_exists(misp_object.id)) - def test_simple_event(self): + def test_simple_event(self) -> None: '''Search a bunch of parameters: * Value not existing * only return metadata @@ -1003,7 +1022,7 @@ class TestComprehensive(unittest.TestCase): self.admin_misp_connector.delete_event(first) self.admin_misp_connector.delete_event(second) - def test_event_add_update_metadata(self): + def test_event_add_update_metadata(self) -> None: event = self.create_simple_event() event.add_attribute('ip-src', '9.9.9.9') try: @@ -1017,7 +1036,7 @@ class TestComprehensive(unittest.TestCase): finally: # cleanup self.admin_misp_connector.delete_event(event) - def test_extend_event(self): + def test_extend_event(self) -> None: first = self.create_simple_event() first.info = 'parent event' first.add_tag('tlp:amber___test') @@ -1038,7 +1057,7 @@ class TestComprehensive(unittest.TestCase): self.admin_misp_connector.delete_event(first) self.admin_misp_connector.delete_event(second) - def test_edit_attribute(self): + def test_edit_attribute(self) -> None: first = self.create_simple_event() try: first.attributes[0].comment = 'This is the original comment' @@ -1058,7 +1077,7 @@ class TestComprehensive(unittest.TestCase): # Delete event self.admin_misp_connector.delete_event(first) - def test_sightings(self): + def test_sightings(self) -> None: first = self.create_simple_event() second = self.create_simple_event() try: @@ -1133,7 +1152,7 @@ class TestComprehensive(unittest.TestCase): self.admin_misp_connector.delete_event(first) self.admin_misp_connector.delete_event(second) - def test_search_csv(self): + def test_search_csv(self) -> None: first = self.create_simple_event() first.attributes[0].comment = 'This is the original comment' second = self.create_simple_event() @@ -1213,7 +1232,7 @@ class TestComprehensive(unittest.TestCase): self.admin_misp_connector.delete_event(first) self.admin_misp_connector.delete_event(second) - def test_search_text(self): + def test_search_text(self) -> None: first = self.create_simple_event() first.add_attribute('ip-src', '8.8.8.8') first.publish() @@ -1227,7 +1246,7 @@ class TestComprehensive(unittest.TestCase): # Delete event self.admin_misp_connector.delete_event(first) - def test_search_stix(self): + def test_search_stix(self) -> None: first = self.create_simple_event() first.add_attribute('ip-src', '8.8.8.8') try: @@ -1242,7 +1261,7 @@ class TestComprehensive(unittest.TestCase): # Delete event self.admin_misp_connector.delete_event(first) - def test_update_object(self): + def test_update_object(self) -> None: first = self.create_simple_event() ip_dom = MISPObject('domain-ip') ip_dom.add_attribute('domain', value='google.fr') @@ -1346,7 +1365,7 @@ class TestComprehensive(unittest.TestCase): self.admin_misp_connector.delete_event(first) self.admin_misp_connector.delete_event(second) - def test_custom_template(self): + def test_custom_template(self) -> None: first = self.create_simple_event() try: with open('tests/viper-test-files/test_files/whoami.exe', 'rb') as f: @@ -1388,7 +1407,7 @@ class TestComprehensive(unittest.TestCase): # Delete event self.admin_misp_connector.delete_event(first) - def test_unknown_template(self): + def test_unknown_template(self) -> None: first = self.create_simple_event() attributeAsDict = [{'MyCoolAttribute': {'value': 'critical thing', 'type': 'text'}}, {'MyCoolerAttribute': {'value': 'even worse', 'type': 'text', 'disable_correlation': True}}] @@ -1422,7 +1441,7 @@ class TestComprehensive(unittest.TestCase): # Delete event self.admin_misp_connector.delete_event(first) - def test_domain_ip_object(self): + def test_domain_ip_object(self) -> None: first = self.create_simple_event() try: dom_ip_obj = DomainIPObject({'ip': ['1.1.1.1', {'value': '2.2.2.2', 'to_ids': False}], @@ -1436,7 +1455,7 @@ class TestComprehensive(unittest.TestCase): # Delete event self.admin_misp_connector.delete_event(first) - def test_asn_object(self): + def test_asn_object(self) -> None: first = self.create_simple_event() try: dom_ip_obj = ASNObject({'asn': '12345', @@ -1449,7 +1468,7 @@ class TestComprehensive(unittest.TestCase): # Delete event self.admin_misp_connector.delete_event(first) - def test_object_template(self): + def test_object_template(self) -> None: r = self.admin_misp_connector.update_object_templates() self.assertEqual(type(r), list) object_templates = self.admin_misp_connector.object_templates(pythonify=True) @@ -1468,7 +1487,7 @@ class TestComprehensive(unittest.TestCase): mo.add_attribute('domain', 'google.fr') self.assertEqual(mo.template_uuid, '4') - def test_tags(self): + def test_tags(self) -> None: # Get list tags = self.admin_misp_connector.tags(pythonify=True) self.assertTrue(isinstance(tags, list)) @@ -1557,7 +1576,7 @@ class TestComprehensive(unittest.TestCase): response = self.admin_misp_connector.delete_tag(tag_org_restricted) response = self.admin_misp_connector.delete_tag(tag_user_restricted) - def test_add_event_with_attachment_object_controller(self): + def test_add_event_with_attachment_object_controller(self) -> None: first = self.create_simple_event() try: first = self.user_misp_connector.add_event(first) @@ -1597,7 +1616,7 @@ class TestComprehensive(unittest.TestCase): # Delete event self.admin_misp_connector.delete_event(first) - def test_add_event_with_attachment_object_controller__hard(self): + def test_add_event_with_attachment_object_controller__hard(self) -> None: first = self.create_simple_event() try: first = self.user_misp_connector.add_event(first) @@ -1638,7 +1657,7 @@ class TestComprehensive(unittest.TestCase): # Delete event self.admin_misp_connector.delete_event(first) - def test_lief_and_sign(self): + def test_lief_and_sign(self) -> None: first = self.create_simple_event() try: first = self.user_misp_connector.add_event(first) @@ -1682,7 +1701,7 @@ class TestComprehensive(unittest.TestCase): # Delete event self.admin_misp_connector.delete_event(first) - def test_add_event_with_attachment(self): + def test_add_event_with_attachment(self) -> None: first = self.create_simple_event() try: first = self.user_misp_connector.add_event(first) @@ -1700,7 +1719,7 @@ class TestComprehensive(unittest.TestCase): # Delete event self.admin_misp_connector.delete_event(first) - def test_taxonomies(self): + def test_taxonomies(self) -> None: # Make sure we're up-to-date r = self.admin_misp_connector.update_taxonomies() self.assertEqual(r['name'], 'All taxonomy libraries are up to date already.') @@ -1740,7 +1759,7 @@ class TestComprehensive(unittest.TestCase): # Return back to default required status r = self.admin_misp_connector.set_taxonomy_required(tax, not tax.required) - def test_warninglists(self): + def test_warninglists(self) -> None: # Make sure we're up-to-date r = self.admin_misp_connector.update_warninglists() self.assertTrue('name' in r, msg=r) @@ -1769,7 +1788,7 @@ class TestComprehensive(unittest.TestCase): r = self.admin_misp_connector.disable_warninglist(testwl) self.assertEqual(r['success'], '1 warninglist(s) disabled') - def test_noticelists(self): + def test_noticelists(self) -> None: # Make sure we're up-to-date r = self.admin_misp_connector.update_noticelists() self.assertEqual(r['name'], 'All noticelists are up to date already.') @@ -1790,7 +1809,7 @@ class TestComprehensive(unittest.TestCase): r = self.admin_misp_connector.disable_noticelist(testnl) self.assertFalse(r['Noticelist']['enabled'], r) - def test_correlation_exclusions(self): + def test_correlation_exclusions(self) -> None: newce = MISPCorrelationExclusion() newce.value = "test-correlation-exclusion" r = self.admin_misp_connector.add_correlation_exclusion(newce, pythonify=True) @@ -1805,7 +1824,7 @@ class TestComprehensive(unittest.TestCase): r = self.admin_misp_connector.clean_correlation_exclusions() self.assertTrue(r['success']) - def test_galaxies(self): + def test_galaxies(self) -> None: # Make sure we're up-to-date r = self.admin_misp_connector.update_galaxies() self.assertEqual(r['name'], 'Galaxies updated.') @@ -1821,7 +1840,7 @@ class TestComprehensive(unittest.TestCase): # FIXME: Fails due to https://github.com/MISP/MISP/issues/4855 # self.assertTrue('GalaxyCluster' in r) - def test_zmq(self): + def test_zmq(self) -> None: first = self.create_simple_event() try: first = self.user_misp_connector.add_event(first) @@ -1831,7 +1850,7 @@ class TestComprehensive(unittest.TestCase): # Delete event self.admin_misp_connector.delete_event(first) - def test_csv_loader(self): + def test_csv_loader(self) -> None: csv1 = CSVLoader(template_name='file', csv_path=Path('tests/csv_testfiles/valid_fieldnames.csv')) event = MISPEvent() event.info = 'Test event from CSV loader' @@ -1849,7 +1868,7 @@ class TestComprehensive(unittest.TestCase): # Delete event self.admin_misp_connector.delete_event(first) - def test_user(self): + def test_user(self) -> None: # Get list users = self.admin_misp_connector.users(pythonify=True) self.assertTrue(isinstance(users, list)) @@ -1871,7 +1890,7 @@ class TestComprehensive(unittest.TestCase): key = self.user_misp_connector.get_new_authkey() self.assertTrue(isinstance(key, str)) - def test_organisation(self): + def test_organisation(self) -> None: # Get list orgs = self.admin_misp_connector.organisations(pythonify=True) self.assertTrue(isinstance(orgs, list)) @@ -1888,7 +1907,7 @@ class TestComprehensive(unittest.TestCase): organisation = self.admin_misp_connector.update_organisation(organisation, pythonify=True) self.assertEqual(organisation.name, 'blah', organisation) - def test_org_search(self): + def test_org_search(self) -> None: orgs = self.admin_misp_connector.organisations(pythonify=True) org_name = 'ORGNAME' # Search by the org name @@ -1899,7 +1918,7 @@ class TestComprehensive(unittest.TestCase): # This org should have the name ORGNAME self.assertEqual(orgs[0].name, org_name) - def test_user_search(self): + def test_user_search(self) -> None: users = self.admin_misp_connector.users(pythonify=True) emailAddr = users[0].email @@ -1915,7 +1934,7 @@ class TestComprehensive(unittest.TestCase): self.assertTrue(len(users) == 1) self.assertEqual(users[0].email, emailAddr) - def test_attribute(self): + def test_attribute(self) -> None: first = self.create_simple_event() second = self.create_simple_event() a = second.add_attribute('ip-src', '11.11.11.11') @@ -2084,7 +2103,7 @@ class TestComprehensive(unittest.TestCase): self.admin_misp_connector.delete_event(first) self.admin_misp_connector.delete_event(second) - def test_search_type_event_csv(self): + def test_search_type_event_csv(self) -> None: try: first, second, third = self.environment() # Search as admin @@ -2103,7 +2122,7 @@ class TestComprehensive(unittest.TestCase): self.admin_misp_connector.delete_event(third) @unittest.skip("Not very important, skip for now.") - def test_search_logs(self): + def test_search_logs(self) -> None: r = self.admin_misp_connector.update_user({'email': 'testusr-changed@user.local'}, self.test_usr) r = self.admin_misp_connector.search_logs(model='User', created=date.today(), pythonify=True) for entry in r[-1:]: @@ -2121,22 +2140,22 @@ class TestComprehensive(unittest.TestCase): else: raise Exception('Unable to find log entry after updating the user') - def test_db_schema(self): + def test_db_schema(self) -> None: diag = self.admin_misp_connector.db_schema_diagnostic() self.assertEqual(diag['actual_db_version'], diag['expected_db_version'], diag) - def test_live_acl(self): + def test_live_acl(self) -> None: missing_acls = self.admin_misp_connector.remote_acl() self.assertEqual(missing_acls, [], msg=missing_acls) - def test_roles(self): + def test_roles(self) -> None: role = self.admin_misp_connector.set_default_role(4) self.assertEqual(role['message'], 'Default role set.') self.admin_misp_connector.set_default_role(3) roles = self.admin_misp_connector.roles(pythonify=True) self.assertTrue(isinstance(roles, list)) - def test_describe_types(self): + def test_describe_types(self) -> None: remote = self.admin_misp_connector.describe_types_remote remote_types = remote.pop('types') remote_categories = remote.pop('categories') @@ -2155,12 +2174,12 @@ class TestComprehensive(unittest.TestCase): for typ in mapping: self.assertIn(typ, remote_types) - def test_versions(self): + def test_versions(self) -> None: self.assertEqual(self.user_misp_connector.version, self.user_misp_connector.pymisp_version_master) self.assertEqual(self.user_misp_connector.misp_instance_version['version'], self.user_misp_connector.misp_instance_version_master['version']) - def test_statistics(self): + def test_statistics(self) -> None: try: # Attributes first, second, third = self.environment() @@ -2209,7 +2228,7 @@ class TestComprehensive(unittest.TestCase): self.admin_misp_connector.delete_event(second) self.admin_misp_connector.delete_event(third) - def test_direct(self): + def test_direct(self) -> None: try: r = self.user_misp_connector.direct_call('events/add', data={'info': 'foo'}) event = MISPEvent() @@ -2226,7 +2245,7 @@ class TestComprehensive(unittest.TestCase): finally: self.admin_misp_connector.delete_event(event) - def test_freetext(self): + def test_freetext(self) -> None: first = self.create_simple_event() try: self.admin_misp_connector.toggle_warninglist(warninglist_name='%dns resolv%', force_enable=True) @@ -2262,7 +2281,7 @@ class TestComprehensive(unittest.TestCase): # Delete event self.admin_misp_connector.delete_event(first) - def test_sharing_groups(self): + def test_sharing_groups(self) -> None: # add sg = MISPSharingGroup() sg.name = 'Testcases SG' @@ -2338,7 +2357,7 @@ class TestComprehensive(unittest.TestCase): self.assertFalse(self.admin_misp_connector.sharing_group_exists(sharing_group.id)) self.assertFalse(self.admin_misp_connector.sharing_group_exists(sharing_group.uuid)) - def test_sharing_group(self): + def test_sharing_group(self) -> None: # add sg = MISPSharingGroup() sg.name = 'Testcases SG' @@ -2363,7 +2382,7 @@ class TestComprehensive(unittest.TestCase): self.admin_misp_connector.delete_sharing_group(sharing_group.id) self.assertFalse(self.admin_misp_connector.sharing_group_exists(sharing_group)) - def test_sharing_group_search(self): + def test_sharing_group_search(self) -> None: # Add sharing group sg = MISPSharingGroup() sg.name = 'Testcases SG' @@ -2410,7 +2429,7 @@ class TestComprehensive(unittest.TestCase): self.assertFalse(self.admin_misp_connector.sharing_group_exists(sharing_group)) - def test_feeds(self): + def test_feeds(self) -> None: # Add feed = MISPFeed() feed.name = 'TestFeed' @@ -2493,7 +2512,7 @@ class TestComprehensive(unittest.TestCase): self.assertFalse(updated_feed.enabled) self.assertEqual(updated_feed.settings, e_thread_csv_feed.settings) - def test_servers(self): + def test_servers(self) -> None: # add server = MISPServer() server.name = 'Test Server' @@ -2513,7 +2532,7 @@ class TestComprehensive(unittest.TestCase): r = self.admin_misp_connector.delete_server(server) self.assertEqual(r['name'], 'Server deleted') - def test_roles_expanded(self): + def test_roles_expanded(self) -> None: '''Test all possible things regarding roles 1. Use existing roles (ID in test VM): * Read only (6): Can only connect via API and see events visible by its organisation @@ -2631,7 +2650,7 @@ class TestComprehensive(unittest.TestCase): self.admin_misp_connector.delete_user(test_roles_user) self.admin_misp_connector.delete_tag(test_tag) - def test_expansion(self): + def test_expansion(self) -> None: first = self.create_simple_event() try: md5_disk = hashlib.md5() @@ -2668,7 +2687,7 @@ class TestComprehensive(unittest.TestCase): # Delete event self.admin_misp_connector.delete_event(first) - def test_user_settings(self): + def test_user_settings(self) -> None: first = self.create_simple_event() first.distribution = 3 first.add_tag('test_publish_filter') @@ -2729,7 +2748,7 @@ class TestComprehensive(unittest.TestCase): self.admin_misp_connector.delete_event(first) self.admin_misp_connector.delete_event(second) - def test_communities(self): + def test_communities(self) -> None: communities = self.admin_misp_connector.communities(pythonify=True) self.assertEqual(communities[0].name, 'CIRCL Private Sector Information Sharing Community - aka MISPPRIV') community = self.admin_misp_connector.get_community(communities[1], pythonify=True) @@ -2743,7 +2762,7 @@ class TestComprehensive(unittest.TestCase): # if k == 'To': # self.assertEqual(v, 'info@circl.lu') - def test_upload_stix(self): + def test_upload_stix(self) -> None: # FIXME https://github.com/MISP/MISP/issues/4892 try: r1 = self.user_misp_connector.upload_stix('tests/stix1.xml-utf8', version='1') @@ -2774,7 +2793,7 @@ class TestComprehensive(unittest.TestCase): except Exception: pass - def test_toggle_global_pythonify(self): + def test_toggle_global_pythonify(self) -> None: first = self.create_simple_event() second = self.create_simple_event() try: @@ -2789,7 +2808,7 @@ class TestComprehensive(unittest.TestCase): self.admin_misp_connector.delete_event(first) self.admin_misp_connector.delete_event(second) - def test_first_last_seen(self): + def test_first_last_seen(self) -> None: event = MISPEvent() event.info = 'Test First Last seen' event.add_attribute('ip-dst', '8.8.8.8', first_seen='2020-01-03', last_seen='2020-01-04T12:30:34.323242+0800') @@ -2836,7 +2855,7 @@ class TestComprehensive(unittest.TestCase): finally: self.admin_misp_connector.delete_event(first) - def test_registrations(self): + def test_registrations(self) -> None: r = register_user(url, 'self_register@user.local', organisation=self.test_org, org_name=self.test_org.name, verify=verifycert) self.assertTrue(r['saved']) @@ -2866,7 +2885,7 @@ class TestComprehensive(unittest.TestCase): m = self.admin_misp_connector.discard_user_registration(registrations[1].id) self.assertEqual(m['name'], '1 registration(s) discarded.') - def test_search_workflow(self): + def test_search_workflow(self) -> None: first = self.create_simple_event() first.add_attribute('domain', 'google.com') tag = MISPTag() @@ -2915,7 +2934,7 @@ class TestComprehensive(unittest.TestCase): self.admin_misp_connector.delete_event(first) self.admin_misp_connector.delete_tag(tag) - def test_search_workflow_ts(self): + def test_search_workflow_ts(self) -> None: first = self.create_simple_event() first.add_attribute('domain', 'google.com') tag = MISPTag() @@ -2964,14 +2983,14 @@ class TestComprehensive(unittest.TestCase): self.admin_misp_connector.delete_event(first) self.admin_misp_connector.delete_tag(tag) - def test_blocklists(self): + def test_blocklists(self) -> None: first = self.create_simple_event() second = self.create_simple_event() second.Orgc = self.test_org - to_delete = {'bl_events': [], 'bl_organisations': []} + to_delete: dict[str, MISPOrganisationBlocklist | MISPEventBlocklist] = {'bl_events': [], 'bl_organisations': []} try: # test events BL - ebl = self.admin_misp_connector.add_event_blocklist(uuids=[first.uuid]) + ebl: MISPEventBlocklist = self.admin_misp_connector.add_event_blocklist(uuids=[first.uuid]) self.assertEqual(ebl['result']['successes'][0], first.uuid, ebl) bl_events = self.admin_misp_connector.event_blocklists(pythonify=True) for ble in bl_events: @@ -3005,7 +3024,7 @@ class TestComprehensive(unittest.TestCase): blo.comment = 'This is a test' blo.org_name = 'bar' - blo = self.admin_misp_connector.update_organisation_blocklist(blo, pythonify=True) + blo: MISPOrganisationBlocklist = self.admin_misp_connector.update_organisation_blocklist(blo, pythonify=True) self.assertEqual(blo.org_name, 'bar') r = self.admin_misp_connector.delete_organisation_blocklist(blo) self.assertTrue(r['success']) @@ -3016,15 +3035,15 @@ class TestComprehensive(unittest.TestCase): for blo in to_delete['bl_organisations']: self.admin_misp_connector.delete_organisation_blocklist(blo) - def test_event_report(self): + def test_event_report(self) -> None: event = self.create_simple_event() - new_event_report = MISPEventReport() + new_event_report: MISPEventReport = MISPEventReport() new_event_report.name = "Test Event Report" new_event_report.content = "# Example report markdown" new_event_report.distribution = 5 # Inherit try: event = self.user_misp_connector.add_event(event) - new_event_report = self.user_misp_connector.add_event_report(event.id, new_event_report) + new_event_report = self.user_misp_connector.add_event_report(event.id, new_event_report) # type: ignore[assignment] # The event report should be linked by Event ID self.assertEqual(event.id, new_event_report.event_id) @@ -3034,12 +3053,12 @@ class TestComprehensive(unittest.TestCase): new_event_report.name = "Updated Event Report" new_event_report.content = "Updated content" - new_event_report = self.user_misp_connector.update_event_report(new_event_report) + new_event_report = self.user_misp_connector.update_event_report(new_event_report) # type: ignore[assignment] # The event report should be updatable self.assertTrue(new_event_report.name == "Updated Event Report") self.assertTrue(new_event_report.content == "Updated content") - event_reports = self.user_misp_connector.get_event_reports(event.id) + event_reports: list[MISPEventReport] = self.user_misp_connector.get_event_reports(event.id) # type: ignore[assignment] # The event report should be requestable by the Event ID self.assertEqual(new_event_report.id, event_reports[0].id) @@ -3054,33 +3073,41 @@ class TestComprehensive(unittest.TestCase): self.user_misp_connector.delete_event(event) self.user_misp_connector.delete_event_report(new_event_report) - def test_search_galaxy(self): + def test_search_galaxy(self) -> None: self.admin_misp_connector.toggle_global_pythonify() - galaxy = self.admin_misp_connector.galaxies()[0] + galaxies: list[MISPGalaxy] = self.admin_misp_connector.galaxies() # type: ignore[assignment] + galaxy: MISPGalaxy = galaxies[0] ret = self.admin_misp_connector.search_galaxy(value=galaxy.name) self.assertEqual(len(ret), 1) self.admin_misp_connector.toggle_global_pythonify() - def test_galaxy_cluster(self): + def test_galaxy_cluster(self) -> None: self.admin_misp_connector.toggle_global_pythonify() - galaxy = self.admin_misp_connector.galaxies()[0] - new_galaxy_cluster = MISPGalaxyCluster() + galaxies: list[MISPGalaxy] = self.admin_misp_connector.galaxies() # type: ignore[assignment] + galaxy: MISPGalaxy = galaxies[0] + new_galaxy_cluster: MISPGalaxyCluster = MISPGalaxyCluster() new_galaxy_cluster.value = "Test Cluster" new_galaxy_cluster.authors = ["MISP"] new_galaxy_cluster.distribution = 1 new_galaxy_cluster.description = "Example test cluster" try: - galaxy = self.admin_misp_connector.get_galaxy(galaxy.id, withCluster=True) + if gid := galaxy.id: + galaxy = self.admin_misp_connector.get_galaxy(gid, withCluster=True) # type: ignore[assignment] + else: + raise Exception("No galaxy found") existing_galaxy_cluster = galaxy.clusters[0] - new_galaxy_cluster = self.admin_misp_connector.add_galaxy_cluster(galaxy.id, new_galaxy_cluster) + if gid := galaxy.id: + new_galaxy_cluster = self.admin_misp_connector.add_galaxy_cluster(gid, new_galaxy_cluster) # type: ignore[assignment] + else: + raise Exception("No galaxy found") # The new galaxy cluster should be under the selected galaxy self.assertEqual(galaxy.id, new_galaxy_cluster.galaxy_id) # The cluster should have the right value self.assertEqual(new_galaxy_cluster.value, "Test Cluster") new_galaxy_cluster.add_cluster_element("synonyms", "Test2") - new_galaxy_cluster = self.admin_misp_connector.update_galaxy_cluster(new_galaxy_cluster) + new_galaxy_cluster = self.admin_misp_connector.update_galaxy_cluster(new_galaxy_cluster) # type: ignore[assignment] # The cluster should have one element that is a synonym self.assertEqual(len(new_galaxy_cluster.cluster_elements), 1) @@ -3093,22 +3120,22 @@ class TestComprehensive(unittest.TestCase): # The cluster element should be updatable element.value = "Test3" - new_galaxy_cluster = self.admin_misp_connector.update_galaxy_cluster(new_galaxy_cluster) + new_galaxy_cluster = self.admin_misp_connector.update_galaxy_cluster(new_galaxy_cluster) # type: ignore[assignment] element = new_galaxy_cluster.cluster_elements[0] self.assertEqual(element.value, "Test3") new_galaxy_cluster.add_cluster_element("synonyms", "ToDelete") - new_galaxy_cluster = self.admin_misp_connector.update_galaxy_cluster(new_galaxy_cluster) + new_galaxy_cluster = self.admin_misp_connector.update_galaxy_cluster(new_galaxy_cluster) # type: ignore[assignment] # The cluster should have two elements self.assertEqual(len(new_galaxy_cluster.cluster_elements), 2) new_galaxy_cluster.cluster_elements = [e for e in new_galaxy_cluster.cluster_elements if e.value != "ToDelete"] - new_galaxy_cluster = self.admin_misp_connector.update_galaxy_cluster(new_galaxy_cluster) + new_galaxy_cluster = self.admin_misp_connector.update_galaxy_cluster(new_galaxy_cluster) # type: ignore[assignment] # The cluster elements should be deletable self.assertEqual(len(new_galaxy_cluster.cluster_elements), 1) new_galaxy_cluster.add_cluster_relation(existing_galaxy_cluster, "is-tested-by") - new_galaxy_cluster = self.admin_misp_connector.update_galaxy_cluster(new_galaxy_cluster) + new_galaxy_cluster = self.admin_misp_connector.update_galaxy_cluster(new_galaxy_cluster) # type: ignore[assignment] # The cluster should have a relationship self.assertEqual(len(new_galaxy_cluster.cluster_relations), 1) relation = new_galaxy_cluster.cluster_relations[0] @@ -3116,7 +3143,7 @@ class TestComprehensive(unittest.TestCase): self.assertEqual(relation.referenced_galaxy_cluster_uuid, existing_galaxy_cluster.uuid) relation.add_tag("tlp:amber") - new_galaxy_cluster = self.admin_misp_connector.update_galaxy_cluster(new_galaxy_cluster) + new_galaxy_cluster = self.admin_misp_connector.update_galaxy_cluster(new_galaxy_cluster) # type: ignore[assignment] relation = new_galaxy_cluster.cluster_relations[0] # The relationship should have a tag of tlp:amber self.assertEqual(len(relation.tags), 1) @@ -3126,32 +3153,36 @@ class TestComprehensive(unittest.TestCase): resp = self.admin_misp_connector.delete_galaxy_cluster_relation(relation) self.assertTrue(resp['success']) # The cluster relation should no longer be present - new_galaxy_cluster = self.admin_misp_connector.get_galaxy_cluster(new_galaxy_cluster) + new_galaxy_cluster = self.admin_misp_connector.get_galaxy_cluster(new_galaxy_cluster) # type: ignore[assignment] self.assertEqual(len(new_galaxy_cluster.cluster_relations), 0) resp = self.admin_misp_connector.delete_galaxy_cluster(new_galaxy_cluster) # Galaxy clusters should be soft deletable self.assertTrue(resp['success']) - new_galaxy_cluster = self.admin_misp_connector.get_galaxy_cluster(new_galaxy_cluster) + new_galaxy_cluster = self.admin_misp_connector.get_galaxy_cluster(new_galaxy_cluster) # type: ignore[assignment] self.assertTrue(isinstance(new_galaxy_cluster, MISPGalaxyCluster)) resp = self.admin_misp_connector.delete_galaxy_cluster(new_galaxy_cluster, hard=True) # Galaxy clusters should be hard deletable self.assertTrue(resp['success']) - resp = self.admin_misp_connector.get_galaxy_cluster(new_galaxy_cluster) + resp = self.admin_misp_connector.get_galaxy_cluster(new_galaxy_cluster) # type: ignore[assignment] self.assertTrue("errors" in resp) finally: self.admin_misp_connector.delete_galaxy_cluster_relation(relation) self.admin_misp_connector.delete_galaxy_cluster(new_galaxy_cluster, hard=True) self.admin_misp_connector.toggle_global_pythonify() - def test_event_galaxy(self): + def test_event_galaxy(self) -> None: self.admin_misp_connector.toggle_global_pythonify() event = self.create_simple_event() try: - galaxy = self.admin_misp_connector.galaxies()[0] - galaxy = self.admin_misp_connector.get_galaxy(galaxy.id, withCluster=True) - galaxy_cluster = galaxy.clusters[0] + galaxies: list[MISPGalaxy] = self.admin_misp_connector.galaxies() # type: ignore[assignment] + galaxy: MISPGalaxy = galaxies[0] + if gid := galaxy.id: + galaxy = self.admin_misp_connector.get_galaxy(gid, withCluster=True) # type: ignore[assignment] + else: + raise Exception("No galaxy found") + galaxy_cluster: MISPGalaxyCluster = galaxy.clusters[0] event.add_tag(galaxy_cluster.tag_name) event = self.admin_misp_connector.add_event(event) # The event should have a galaxy attached @@ -3166,7 +3197,7 @@ class TestComprehensive(unittest.TestCase): self.admin_misp_connector.toggle_global_pythonify() @unittest.skip("Internal use only") - def missing_methods(self): + def missing_methods(self) -> None: skip = [ "attributes/download", "attributes/add_attachment", From daf82f41f41877ec5b9331417049169e2008e3ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Vinot?= Date: Thu, 1 Feb 2024 14:41:11 +0100 Subject: [PATCH 53/80] chg: Bump deps --- poetry.lock | 262 ++++++++++++++++++++++++------------------------- pyproject.toml | 6 +- 2 files changed, 131 insertions(+), 137 deletions(-) diff --git a/poetry.lock b/poetry.lock index 2703083..5a64b9b 100644 --- a/poetry.lock +++ b/poetry.lock @@ -658,63 +658,63 @@ files = [ [[package]] name = "coverage" -version = "7.4.0" +version = "7.4.1" description = "Code coverage measurement for Python" optional = false python-versions = ">=3.8" files = [ - {file = "coverage-7.4.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:36b0ea8ab20d6a7564e89cb6135920bc9188fb5f1f7152e94e8300b7b189441a"}, - {file = "coverage-7.4.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0676cd0ba581e514b7f726495ea75aba3eb20899d824636c6f59b0ed2f88c471"}, - {file = "coverage-7.4.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d0ca5c71a5a1765a0f8f88022c52b6b8be740e512980362f7fdbb03725a0d6b9"}, - {file = "coverage-7.4.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a7c97726520f784239f6c62506bc70e48d01ae71e9da128259d61ca5e9788516"}, - {file = "coverage-7.4.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:815ac2d0f3398a14286dc2cea223a6f338109f9ecf39a71160cd1628786bc6f5"}, - {file = "coverage-7.4.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:80b5ee39b7f0131ebec7968baa9b2309eddb35b8403d1869e08f024efd883566"}, - {file = "coverage-7.4.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:5b2ccb7548a0b65974860a78c9ffe1173cfb5877460e5a229238d985565574ae"}, - {file = "coverage-7.4.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:995ea5c48c4ebfd898eacb098164b3cc826ba273b3049e4a889658548e321b43"}, - {file = "coverage-7.4.0-cp310-cp310-win32.whl", hash = "sha256:79287fd95585ed36e83182794a57a46aeae0b64ca53929d1176db56aacc83451"}, - {file = "coverage-7.4.0-cp310-cp310-win_amd64.whl", hash = "sha256:5b14b4f8760006bfdb6e08667af7bc2d8d9bfdb648351915315ea17645347137"}, - {file = "coverage-7.4.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:04387a4a6ecb330c1878907ce0dc04078ea72a869263e53c72a1ba5bbdf380ca"}, - {file = "coverage-7.4.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ea81d8f9691bb53f4fb4db603203029643caffc82bf998ab5b59ca05560f4c06"}, - {file = "coverage-7.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:74775198b702868ec2d058cb92720a3c5a9177296f75bd97317c787daf711505"}, - {file = "coverage-7.4.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:76f03940f9973bfaee8cfba70ac991825611b9aac047e5c80d499a44079ec0bc"}, - {file = "coverage-7.4.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:485e9f897cf4856a65a57c7f6ea3dc0d4e6c076c87311d4bc003f82cfe199d25"}, - {file = "coverage-7.4.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:6ae8c9d301207e6856865867d762a4b6fd379c714fcc0607a84b92ee63feff70"}, - {file = "coverage-7.4.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:bf477c355274a72435ceb140dc42de0dc1e1e0bf6e97195be30487d8eaaf1a09"}, - {file = "coverage-7.4.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:83c2dda2666fe32332f8e87481eed056c8b4d163fe18ecc690b02802d36a4d26"}, - {file = "coverage-7.4.0-cp311-cp311-win32.whl", hash = "sha256:697d1317e5290a313ef0d369650cfee1a114abb6021fa239ca12b4849ebbd614"}, - {file = "coverage-7.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:26776ff6c711d9d835557ee453082025d871e30b3fd6c27fcef14733f67f0590"}, - {file = "coverage-7.4.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:13eaf476ec3e883fe3e5fe3707caeb88268a06284484a3daf8250259ef1ba143"}, - {file = "coverage-7.4.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:846f52f46e212affb5bcf131c952fb4075b55aae6b61adc9856222df89cbe3e2"}, - {file = "coverage-7.4.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:26f66da8695719ccf90e794ed567a1549bb2644a706b41e9f6eae6816b398c4a"}, - {file = "coverage-7.4.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:164fdcc3246c69a6526a59b744b62e303039a81e42cfbbdc171c91a8cc2f9446"}, - {file = "coverage-7.4.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:316543f71025a6565677d84bc4df2114e9b6a615aa39fb165d697dba06a54af9"}, - {file = "coverage-7.4.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:bb1de682da0b824411e00a0d4da5a784ec6496b6850fdf8c865c1d68c0e318dd"}, - {file = "coverage-7.4.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:0e8d06778e8fbffccfe96331a3946237f87b1e1d359d7fbe8b06b96c95a5407a"}, - {file = "coverage-7.4.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:a56de34db7b7ff77056a37aedded01b2b98b508227d2d0979d373a9b5d353daa"}, - {file = "coverage-7.4.0-cp312-cp312-win32.whl", hash = "sha256:51456e6fa099a8d9d91497202d9563a320513fcf59f33991b0661a4a6f2ad450"}, - {file = "coverage-7.4.0-cp312-cp312-win_amd64.whl", hash = "sha256:cd3c1e4cb2ff0083758f09be0f77402e1bdf704adb7f89108007300a6da587d0"}, - {file = "coverage-7.4.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:e9d1bf53c4c8de58d22e0e956a79a5b37f754ed1ffdbf1a260d9dcfa2d8a325e"}, - {file = "coverage-7.4.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:109f5985182b6b81fe33323ab4707011875198c41964f014579cf82cebf2bb85"}, - {file = "coverage-7.4.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3cc9d4bc55de8003663ec94c2f215d12d42ceea128da8f0f4036235a119c88ac"}, - {file = "coverage-7.4.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cc6d65b21c219ec2072c1293c505cf36e4e913a3f936d80028993dd73c7906b1"}, - {file = "coverage-7.4.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5a10a4920def78bbfff4eff8a05c51be03e42f1c3735be42d851f199144897ba"}, - {file = "coverage-7.4.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:b8e99f06160602bc64da35158bb76c73522a4010f0649be44a4e167ff8555952"}, - {file = "coverage-7.4.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:7d360587e64d006402b7116623cebf9d48893329ef035278969fa3bbf75b697e"}, - {file = "coverage-7.4.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:29f3abe810930311c0b5d1a7140f6395369c3db1be68345638c33eec07535105"}, - {file = "coverage-7.4.0-cp38-cp38-win32.whl", hash = "sha256:5040148f4ec43644702e7b16ca864c5314ccb8ee0751ef617d49aa0e2d6bf4f2"}, - {file = "coverage-7.4.0-cp38-cp38-win_amd64.whl", hash = "sha256:9864463c1c2f9cb3b5db2cf1ff475eed2f0b4285c2aaf4d357b69959941aa555"}, - {file = "coverage-7.4.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:936d38794044b26c99d3dd004d8af0035ac535b92090f7f2bb5aa9c8e2f5cd42"}, - {file = "coverage-7.4.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:799c8f873794a08cdf216aa5d0531c6a3747793b70c53f70e98259720a6fe2d7"}, - {file = "coverage-7.4.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e7defbb9737274023e2d7af02cac77043c86ce88a907c58f42b580a97d5bcca9"}, - {file = "coverage-7.4.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a1526d265743fb49363974b7aa8d5899ff64ee07df47dd8d3e37dcc0818f09ed"}, - {file = "coverage-7.4.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bf635a52fc1ea401baf88843ae8708591aa4adff875e5c23220de43b1ccf575c"}, - {file = "coverage-7.4.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:756ded44f47f330666843b5781be126ab57bb57c22adbb07d83f6b519783b870"}, - {file = "coverage-7.4.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:0eb3c2f32dabe3a4aaf6441dde94f35687224dfd7eb2a7f47f3fd9428e421058"}, - {file = "coverage-7.4.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:bfd5db349d15c08311702611f3dccbef4b4e2ec148fcc636cf8739519b4a5c0f"}, - {file = "coverage-7.4.0-cp39-cp39-win32.whl", hash = "sha256:53d7d9158ee03956e0eadac38dfa1ec8068431ef8058fe6447043db1fb40d932"}, - {file = "coverage-7.4.0-cp39-cp39-win_amd64.whl", hash = "sha256:cfd2a8b6b0d8e66e944d47cdec2f47c48fef2ba2f2dff5a9a75757f64172857e"}, - {file = "coverage-7.4.0-pp38.pp39.pp310-none-any.whl", hash = "sha256:c530833afc4707fe48524a44844493f36d8727f04dcce91fb978c414a8556cc6"}, - {file = "coverage-7.4.0.tar.gz", hash = "sha256:707c0f58cb1712b8809ece32b68996ee1e609f71bd14615bd8f87a1293cb610e"}, + {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] @@ -725,47 +725,40 @@ toml = ["tomli"] [[package]] name = "cryptography" -version = "41.0.7" +version = "42.0.2" description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." optional = false python-versions = ">=3.7" files = [ - {file = "cryptography-41.0.7-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:3c78451b78313fa81607fa1b3f1ae0a5ddd8014c38a02d9db0616133987b9cdf"}, - {file = "cryptography-41.0.7-cp37-abi3-macosx_10_12_x86_64.whl", hash = "sha256:928258ba5d6f8ae644e764d0f996d61a8777559f72dfeb2eea7e2fe0ad6e782d"}, - {file = "cryptography-41.0.7-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5a1b41bc97f1ad230a41657d9155113c7521953869ae57ac39ac7f1bb471469a"}, - {file = "cryptography-41.0.7-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:841df4caa01008bad253bce2a6f7b47f86dc9f08df4b433c404def869f590a15"}, - {file = "cryptography-41.0.7-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:5429ec739a29df2e29e15d082f1d9ad683701f0ec7709ca479b3ff2708dae65a"}, - {file = "cryptography-41.0.7-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:43f2552a2378b44869fe8827aa19e69512e3245a219104438692385b0ee119d1"}, - {file = "cryptography-41.0.7-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:af03b32695b24d85a75d40e1ba39ffe7db7ffcb099fe507b39fd41a565f1b157"}, - {file = "cryptography-41.0.7-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:49f0805fc0b2ac8d4882dd52f4a3b935b210935d500b6b805f321addc8177406"}, - {file = "cryptography-41.0.7-cp37-abi3-win32.whl", hash = "sha256:f983596065a18a2183e7f79ab3fd4c475205b839e02cbc0efbbf9666c4b3083d"}, - {file = "cryptography-41.0.7-cp37-abi3-win_amd64.whl", hash = "sha256:90452ba79b8788fa380dfb587cca692976ef4e757b194b093d845e8d99f612f2"}, - {file = "cryptography-41.0.7-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:079b85658ea2f59c4f43b70f8119a52414cdb7be34da5d019a77bf96d473b960"}, - {file = "cryptography-41.0.7-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:b640981bf64a3e978a56167594a0e97db71c89a479da8e175d8bb5be5178c003"}, - {file = "cryptography-41.0.7-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:e3114da6d7f95d2dee7d3f4eec16dacff819740bbab931aff8648cb13c5ff5e7"}, - {file = "cryptography-41.0.7-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:d5ec85080cce7b0513cfd233914eb8b7bbd0633f1d1703aa28d1dd5a72f678ec"}, - {file = "cryptography-41.0.7-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:7a698cb1dac82c35fcf8fe3417a3aaba97de16a01ac914b89a0889d364d2f6be"}, - {file = "cryptography-41.0.7-pp38-pypy38_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:37a138589b12069efb424220bf78eac59ca68b95696fc622b6ccc1c0a197204a"}, - {file = "cryptography-41.0.7-pp38-pypy38_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:68a2dec79deebc5d26d617bfdf6e8aab065a4f34934b22d3b5010df3ba36612c"}, - {file = "cryptography-41.0.7-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:09616eeaef406f99046553b8a40fbf8b1e70795a91885ba4c96a70793de5504a"}, - {file = "cryptography-41.0.7-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:48a0476626da912a44cc078f9893f292f0b3e4c739caf289268168d8f4702a39"}, - {file = "cryptography-41.0.7-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:c7f3201ec47d5207841402594f1d7950879ef890c0c495052fa62f58283fde1a"}, - {file = "cryptography-41.0.7-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:c5ca78485a255e03c32b513f8c2bc39fedb7f5c5f8535545bdc223a03b24f248"}, - {file = "cryptography-41.0.7-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:d6c391c021ab1f7a82da5d8d0b3cee2f4b2c455ec86c8aebbc84837a631ff309"}, - {file = "cryptography-41.0.7.tar.gz", hash = "sha256:13f93ce9bea8016c253b34afc6bd6a75993e5c40672ed5405a9c832f0d4a00bc"}, + {file = "cryptography-42.0.2-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:701171f825dcab90969596ce2af253143b93b08f1a716d4b2a9d2db5084ef7be"}, + {file = "cryptography-42.0.2-cp37-abi3-macosx_10_12_x86_64.whl", hash = "sha256:61321672b3ac7aade25c40449ccedbc6db72c7f5f0fdf34def5e2f8b51ca530d"}, + {file = "cryptography-42.0.2-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ea2c3ffb662fec8bbbfce5602e2c159ff097a4631d96235fcf0fb00e59e3ece4"}, + {file = "cryptography-42.0.2-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3b15c678f27d66d247132cbf13df2f75255627bcc9b6a570f7d2fd08e8c081d2"}, + {file = "cryptography-42.0.2-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:36d4b7c4be6411f58f60d9ce555a73df8406d484ba12a63549c88bd64f7967f1"}, + {file = "cryptography-42.0.2-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:a00aee5d1b6c20620161984f8ab2ab69134466c51f58c052c11b076715e72929"}, + {file = "cryptography-42.0.2-cp37-abi3-win32.whl", hash = "sha256:4b063d3413f853e056161eb0c7724822a9740ad3caa24b8424d776cebf98e7ee"}, + {file = "cryptography-42.0.2-cp39-abi3-macosx_10_12_universal2.whl", hash = "sha256:55d1580e2d7e17f45d19d3b12098e352f3a37fe86d380bf45846ef257054b242"}, + {file = "cryptography-42.0.2-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b9097a208875fc7bbeb1286d0125d90bdfed961f61f214d3f5be62cd4ed8a446"}, + {file = "cryptography-42.0.2-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:fa3dec4ba8fb6e662770b74f62f1a0c7d4e37e25b58b2bf2c1be4c95372b4a33"}, + {file = "cryptography-42.0.2-cp39-abi3-win32.whl", hash = "sha256:3dbd37e14ce795b4af61b89b037d4bc157f2cb23e676fa16932185a04dfbf635"}, + {file = "cryptography-42.0.2-cp39-abi3-win_amd64.whl", hash = "sha256:8a06641fb07d4e8f6c7dda4fc3f8871d327803ab6542e33831c7ccfdcb4d0ad6"}, + {file = "cryptography-42.0.2-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:a7ef8dd0bf2e1d0a27042b231a3baac6883cdd5557036f5e8df7139255feaac6"}, + {file = "cryptography-42.0.2-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:320948ab49883557a256eab46149df79435a22d2fefd6a66fe6946f1b9d9d008"}, + {file = "cryptography-42.0.2-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:52ed9ebf8ac602385126c9a2fe951db36f2cb0c2538d22971487f89d0de4065a"}, + {file = "cryptography-42.0.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:141e2aa5ba100d3788c0ad7919b288f89d1fe015878b9659b307c9ef867d3a65"}, ] [package.dependencies] -cffi = ">=1.12" +cffi = {version = ">=1.12", markers = "platform_python_implementation != \"PyPy\""} [package.extras] docs = ["sphinx (>=5.3.0)", "sphinx-rtd-theme (>=1.1.1)"] -docstest = ["pyenchant (>=1.6.11)", "sphinxcontrib-spelling (>=4.0.1)", "twine (>=1.12.0)"] +docstest = ["pyenchant (>=1.6.11)", "readme-renderer", "sphinxcontrib-spelling (>=4.0.1)"] nox = ["nox"] -pep8test = ["black", "check-sdist", "mypy", "ruff"] +pep8test = ["check-sdist", "click", "mypy", "ruff"] sdist = ["build"] ssh = ["bcrypt (>=3.1.5)"] -test = ["pretend", "pytest (>=6.2.0)", "pytest-benchmark", "pytest-cov", "pytest-xdist"] +test = ["certifi", "pretend", "pytest (>=6.2.0)", "pytest-benchmark", "pytest-cov", "pytest-xdist"] test-randomorder = ["pytest-randomly"] [[package]] @@ -1127,13 +1120,13 @@ test-extra = ["curio", "matplotlib (!=3.2.0)", "nbformat", "numpy (>=1.22)", "pa [[package]] name = "ipython" -version = "8.20.0" +version = "8.21.0" description = "IPython: Productive Interactive Computing" optional = false python-versions = ">=3.10" files = [ - {file = "ipython-8.20.0-py3-none-any.whl", hash = "sha256:bc9716aad6f29f36c449e30821c9dd0c1c1a7b59ddcc26931685b87b4c569619"}, - {file = "ipython-8.20.0.tar.gz", hash = "sha256:2f21bd3fc1d51550c89ee3944ae04bbc7bc79e129ea0937da6e6c68bfdbf117a"}, + {file = "ipython-8.21.0-py3-none-any.whl", hash = "sha256:1050a3ab8473488d7eee163796b02e511d0735cf43a04ba2a8348bd0f2eaf8a5"}, + {file = "ipython-8.21.0.tar.gz", hash = "sha256:48fbc236fbe0e138b88773fa0437751f14c3645fb483f1d4c5dee58b37e5ce73"}, ] [package.dependencies] @@ -1149,17 +1142,17 @@ stack-data = "*" traitlets = ">=5" [package.extras] -all = ["black", "curio", "docrepr", "exceptiongroup", "ipykernel", "ipyparallel", "ipywidgets", "matplotlib", "matplotlib (!=3.2.0)", "nbconvert", "nbformat", "notebook", "numpy (>=1.23)", "pandas", "pickleshare", "pytest", "pytest-asyncio (<0.22)", "qtconsole", "setuptools (>=18.5)", "sphinx (>=1.3)", "sphinx-rtd-theme", "stack-data", "testpath", "trio", "typing-extensions"] +all = ["black", "curio", "docrepr", "exceptiongroup", "ipykernel", "ipyparallel", "ipywidgets", "matplotlib", "matplotlib (!=3.2.0)", "nbconvert", "nbformat", "notebook", "numpy (>=1.23)", "pandas", "pickleshare", "pytest (<8)", "pytest-asyncio (<0.22)", "qtconsole", "setuptools (>=18.5)", "sphinx (>=1.3)", "sphinx-rtd-theme", "stack-data", "testpath", "trio", "typing-extensions"] black = ["black"] -doc = ["docrepr", "exceptiongroup", "ipykernel", "matplotlib", "pickleshare", "pytest", "pytest-asyncio (<0.22)", "setuptools (>=18.5)", "sphinx (>=1.3)", "sphinx-rtd-theme", "stack-data", "testpath", "typing-extensions"] +doc = ["docrepr", "exceptiongroup", "ipykernel", "matplotlib", "pickleshare", "pytest (<8)", "pytest-asyncio (<0.22)", "setuptools (>=18.5)", "sphinx (>=1.3)", "sphinx-rtd-theme", "stack-data", "testpath", "typing-extensions"] kernel = ["ipykernel"] nbconvert = ["nbconvert"] nbformat = ["nbformat"] notebook = ["ipywidgets", "notebook"] parallel = ["ipyparallel"] qtconsole = ["qtconsole"] -test = ["pickleshare", "pytest", "pytest-asyncio (<0.22)", "testpath"] -test-extra = ["curio", "matplotlib (!=3.2.0)", "nbformat", "numpy (>=1.23)", "pandas", "pickleshare", "pytest", "pytest-asyncio (<0.22)", "testpath", "trio"] +test = ["pickleshare", "pytest (<8)", "pytest-asyncio (<0.22)", "testpath"] +test-extra = ["curio", "matplotlib (!=3.2.0)", "nbformat", "numpy (>=1.23)", "pandas", "pickleshare", "pytest (<8)", "pytest-asyncio (<0.22)", "testpath", "trio"] [[package]] name = "isoduration" @@ -1403,13 +1396,13 @@ test = ["flaky", "ipykernel", "pre-commit", "pytest (>=7.0)", "pytest-console-sc [[package]] name = "jupyter-server-terminals" -version = "0.5.1" +version = "0.5.2" description = "A Jupyter Server Extension Providing Terminals." optional = false python-versions = ">=3.8" files = [ - {file = "jupyter_server_terminals-0.5.1-py3-none-any.whl", hash = "sha256:5e63e947ddd97bb2832db5ef837a258d9ccd4192cd608c1270850ad947ae5dd7"}, - {file = "jupyter_server_terminals-0.5.1.tar.gz", hash = "sha256:16d3be9cf48be6a1f943f3a6c93c033be259cf4779184c66421709cf63dccfea"}, + {file = "jupyter_server_terminals-0.5.2-py3-none-any.whl", hash = "sha256:1b80c12765da979513c42c90215481bbc39bd8ae7c0350b4f85bc3eb58d0fa80"}, + {file = "jupyter_server_terminals-0.5.2.tar.gz", hash = "sha256:396b5ccc0881e550bf0ee7012c6ef1b53edbde69e67cab1d56e89711b46052e8"}, ] [package.dependencies] @@ -1422,13 +1415,13 @@ test = ["jupyter-server (>=2.0.0)", "pytest (>=7.0)", "pytest-jupyter[server] (> [[package]] name = "jupyterlab" -version = "4.0.11" +version = "4.0.12" description = "JupyterLab computational environment" optional = false python-versions = ">=3.8" files = [ - {file = "jupyterlab-4.0.11-py3-none-any.whl", hash = "sha256:536bf0e78723153a5016ca7efb88ed0ecd7070d3f1555d5b0e2770658f900a3c"}, - {file = "jupyterlab-4.0.11.tar.gz", hash = "sha256:d1aec24712566bc25a36229788242778e498ca4088028e2f9aa156b8b7fdc8fc"}, + {file = "jupyterlab-4.0.12-py3-none-any.whl", hash = "sha256:53f132480e5f6564f4e20d1b5ed4e8b7945952a2decd5bdfa43760b1b536c99d"}, + {file = "jupyterlab-4.0.12.tar.gz", hash = "sha256:965d92efa82a538ed70ccb3968d9aabba788840da882e13d7b061780cdedc3b7"}, ] [package.dependencies] @@ -1860,13 +1853,13 @@ full = ["XLMMacroDeobfuscator"] [[package]] name = "overrides" -version = "7.6.0" +version = "7.7.0" description = "A decorator to automatically detect mismatch when overriding a method." optional = false python-versions = ">=3.6" files = [ - {file = "overrides-7.6.0-py3-none-any.whl", hash = "sha256:c36e6635519ea9c5b043b65c36d4b886aee8bd45b7d4681d2a6df0898df4b654"}, - {file = "overrides-7.6.0.tar.gz", hash = "sha256:01e15bbbf15b766f0675c275baa1878bd1c7dc9bc7b9ee13e677cdba93dc1bd9"}, + {file = "overrides-7.7.0-py3-none-any.whl", hash = "sha256:c7ed9d062f78b8e4c1a7b70bd8796b35ead4d9f510227ef9c5dc7626c60d7e49"}, + {file = "overrides-7.7.0.tar.gz", hash = "sha256:55158fa3d93b98cc75299b1e67078ad9003ca27945c76162c1c0766d6f91820a"}, ] [[package]] @@ -2044,28 +2037,28 @@ files = [ [[package]] name = "platformdirs" -version = "4.1.0" +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.1.0-py3-none-any.whl", hash = "sha256:11c8f37bcca40db96d8144522d925583bdb7a31f7b0e37e3ed4318400a8e2380"}, - {file = "platformdirs-4.1.0.tar.gz", hash = "sha256:906d548203468492d432bcb294d4bc2fff751bf84971fbb2c10918cc206ee420"}, + {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.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.1)", "sphinx-autodoc-typehints (>=1.24)"] -test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.4)", "pytest-cov (>=4.1)", "pytest-mock (>=3.11.1)"] +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.3.0" +version = "1.4.0" description = "plugin and hook calling mechanisms for python" optional = false python-versions = ">=3.8" files = [ - {file = "pluggy-1.3.0-py3-none-any.whl", hash = "sha256:d89c696a773f8bd377d18e5ecda92b7a3793cbe66c87060a6fb58c7b6e1061f7"}, - {file = "pluggy-1.3.0.tar.gz", hash = "sha256:cf61ae8f126ac6f7c451172cf30e3e43d3ca77615509771b3a984a0730651e12"}, + {file = "pluggy-1.4.0-py3-none-any.whl", hash = "sha256:7db9f7b503d67d1c5b95f59773ebb58a8c1c288129a88665838012cfb07b8981"}, + {file = "pluggy-1.4.0.tar.gz", hash = "sha256:8c85c2876142a764e5b7548e7d9a0e0ddb46f5185161049a79b7e974454223be"}, ] [package.extras] @@ -2141,13 +2134,13 @@ files = [ [[package]] name = "publicsuffixlist" -version = "0.10.0.20240108" +version = "0.10.0.20240201" description = "publicsuffixlist implement" optional = true python-versions = ">=2.6" files = [ - {file = "publicsuffixlist-0.10.0.20240108-py2.py3-none-any.whl", hash = "sha256:72ac774728036610501353789125a7adc57a793646cf6c6f1f7cc7458c913a8a"}, - {file = "publicsuffixlist-0.10.0.20240108.tar.gz", hash = "sha256:2d15301cbef4b5ecc9bfa47b38959af73350915748d44b2f91db2a8fc3b98d24"}, + {file = "publicsuffixlist-0.10.0.20240201-py2.py3-none-any.whl", hash = "sha256:8cd17d60d8a62a8a5dc37b5a75ffc9fa15c45070a27f114919c5d7c79985b1a7"}, + {file = "publicsuffixlist-0.10.0.20240201.tar.gz", hash = "sha256:f0801faf9e545acb2dcb2a05af9289580b54d4b9c082e100c14496b6cfe22b5a"}, ] [package.extras] @@ -2242,13 +2235,13 @@ files = [ [[package]] name = "pytest" -version = "7.4.4" +version = "8.0.0" description = "pytest: simple powerful testing with Python" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "pytest-7.4.4-py3-none-any.whl", hash = "sha256:b090cdf5ed60bf4c45261be03239c2c1c22df034fbffe691abe93cd80cea01d8"}, - {file = "pytest-7.4.4.tar.gz", hash = "sha256:2cf0005922c6ace4a3e2ec8b4080eb0d9753fdc93107415332f50ce9e7994280"}, + {file = "pytest-8.0.0-py3-none-any.whl", hash = "sha256:50fb9cbe836c3f20f0dfa99c565201fb75dc54c8d76373cd1bde06b06657bdb6"}, + {file = "pytest-8.0.0.tar.gz", hash = "sha256:249b1b0864530ba251b7438274c4d251c58d868edaaec8762893ad4a0d71c36c"}, ] [package.dependencies] @@ -2256,7 +2249,7 @@ colorama = {version = "*", markers = "sys_platform == \"win32\""} exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""} iniconfig = "*" packaging = "*" -pluggy = ">=0.12,<2.0" +pluggy = ">=1.3.0,<2.0" tomli = {version = ">=1.0.0", markers = "python_version < \"3.11\""} [package.extras] @@ -2318,13 +2311,13 @@ files = [ [[package]] name = "pytz" -version = "2023.3.post1" +version = "2023.4" description = "World timezone definitions, modern and historical" optional = false python-versions = "*" files = [ - {file = "pytz-2023.3.post1-py2.py3-none-any.whl", hash = "sha256:ce42d816b81b68506614c11e8937d3aa9e41007ceb50bfdcb0749b921bf646c7"}, - {file = "pytz-2023.3.post1.tar.gz", hash = "sha256:7b4fddbeb94a1eba4b557da24f19fdf9db575192544270a9101d8509f9f43d7b"}, + {file = "pytz-2023.4-py2.py3-none-any.whl", hash = "sha256:f90ef520d95e7c46951105338d918664ebfd6f1d995bd7d153127ce90efafa6a"}, + {file = "pytz-2023.4.tar.gz", hash = "sha256:31d4583c4ed539cd037956140d695e42c033a19e984bfce9964a3f7d59bc2b40"}, ] [[package]] @@ -2557,13 +2550,13 @@ files = [ [[package]] name = "referencing" -version = "0.32.1" +version = "0.33.0" description = "JSON Referencing + Python" optional = false python-versions = ">=3.8" files = [ - {file = "referencing-0.32.1-py3-none-any.whl", hash = "sha256:7e4dc12271d8e15612bfe35792f5ea1c40970dadf8624602e33db2758f7ee554"}, - {file = "referencing-0.32.1.tar.gz", hash = "sha256:3c57da0513e9563eb7e203ebe9bb3a1b509b042016433bd1e45a2853466c3dd3"}, + {file = "referencing-0.33.0-py3-none-any.whl", hash = "sha256:39240f2ecc770258f28b642dd47fd74bc8b02484de54e1882b74b35ebd779bd5"}, + {file = "referencing-0.33.0.tar.gz", hash = "sha256:c775fedf74bc0f9189c2a3be1c12fd03e8c23f4d371dce795df44e06c5b412f7"}, ] [package.dependencies] @@ -2914,22 +2907,22 @@ test = ["cython (>=3.0)", "filelock", "html5lib", "pytest (>=4.6)", "setuptools [[package]] name = "sphinx-autodoc-typehints" -version = "1.25.2" +version = "1.25.3" description = "Type hints (PEP 484) support for the Sphinx autodoc extension" optional = true python-versions = ">=3.8" files = [ - {file = "sphinx_autodoc_typehints-1.25.2-py3-none-any.whl", hash = "sha256:5ed05017d23ad4b937eab3bee9fae9ab0dd63f0b42aa360031f1fad47e47f673"}, - {file = "sphinx_autodoc_typehints-1.25.2.tar.gz", hash = "sha256:3cabc2537e17989b2f92e64a399425c4c8bf561ed73f087bc7414a5003616a50"}, + {file = "sphinx_autodoc_typehints-1.25.3-py3-none-any.whl", hash = "sha256:d3da7fa9a9761eff6ff09f8b1956ae3090a2d4f4ad54aebcade8e458d6340835"}, + {file = "sphinx_autodoc_typehints-1.25.3.tar.gz", hash = "sha256:70db10b391acf4e772019765991d2de0ff30ec0899b9ba137706dc0b3c4835e0"}, ] [package.dependencies] sphinx = ">=7.1.2" [package.extras] -docs = ["furo (>=2023.7.26)", "sphinx (>=7.1.2)"] +docs = ["furo (>=2023.9.10)"] numpy = ["nptyping (>=2.5)"] -testing = ["covdefaults (>=2.3)", "coverage (>=7.3)", "diff-cover (>=7.7)", "pytest (>=7.4)", "pytest-cov (>=4.1)", "sphobjinv (>=2.3.1)", "typing-extensions (>=4.7.1)"] +testing = ["covdefaults (>=2.3)", "coverage (>=7.3.2)", "diff-cover (>=8.0.1)", "pytest (>=7.4.3)", "pytest-cov (>=4.1)", "sphobjinv (>=2.3.1)", "typing-extensions (>=4.8)"] [[package]] name = "sphinxcontrib-applehelp" @@ -3258,13 +3251,13 @@ files = [ [[package]] name = "types-pyopenssl" -version = "23.3.0.20240106" +version = "24.0.0.20240130" description = "Typing stubs for pyOpenSSL" optional = false python-versions = ">=3.8" files = [ - {file = "types-pyOpenSSL-23.3.0.20240106.tar.gz", hash = "sha256:3d6f3462bec0c260caadf93fbb377225c126661b779c7d9ab99b6dad5ca10db9"}, - {file = "types_pyOpenSSL-23.3.0.20240106-py3-none-any.whl", hash = "sha256:47a7eedbd18b7bcad17efebf1c53416148f5a173918a6d75027e75e32fe039ae"}, + {file = "types-pyOpenSSL-24.0.0.20240130.tar.gz", hash = "sha256:c812e5c1c35249f75ef5935708b2a997d62abf9745be222e5f94b9595472ab25"}, + {file = "types_pyOpenSSL-24.0.0.20240130-py3-none-any.whl", hash = "sha256:24a255458b5b8a7fca8139cf56f2a8ad5a4f1a5f711b73a5bb9cb50dc688fab5"}, ] [package.dependencies] @@ -3298,13 +3291,13 @@ types-pyOpenSSL = "*" [[package]] name = "types-requests" -version = "2.31.0.20240106" +version = "2.31.0.20240125" description = "Typing stubs for requests" optional = false python-versions = ">=3.8" files = [ - {file = "types-requests-2.31.0.20240106.tar.gz", hash = "sha256:0e1c731c17f33618ec58e022b614a1a2ecc25f7dc86800b36ef341380402c612"}, - {file = "types_requests-2.31.0.20240106-py3-none-any.whl", hash = "sha256:da997b3b6a72cc08d09f4dba9802fdbabc89104b35fe24ee588e674037689354"}, + {file = "types-requests-2.31.0.20240125.tar.gz", hash = "sha256:03a28ce1d7cd54199148e043b2079cdded22d6795d19a2c2a6791a4b2b5e2eb5"}, + {file = "types_requests-2.31.0.20240125-py3-none-any.whl", hash = "sha256:9592a9a4cb92d6d75d9b491a41477272b710e021011a2a3061157e2fb1f1a5d1"}, ] [package.dependencies] @@ -3377,13 +3370,13 @@ dev = ["flake8", "flake8-annotations", "flake8-bandit", "flake8-bugbear", "flake [[package]] name = "urllib3" -version = "2.1.0" +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.1.0-py3-none-any.whl", hash = "sha256:55901e917a5896a349ff771be919f8bd99aff50b79fe58fec595eb37bbc56bb3"}, - {file = "urllib3-2.1.0.tar.gz", hash = "sha256:df7aa8afb0148fa78488e7899b2c59b5f4ffcfa82e6c54ccb9dd37c1d7b52d54"}, + {file = "urllib3-2.2.0-py3-none-any.whl", hash = "sha256:ce3711610ddce217e6d113a2732fafad960a03fd0318c91faa79481e35c11224"}, + {file = "urllib3-2.2.0.tar.gz", hash = "sha256:051d961ad0c62a94e50ecf1af379c3aba230c66c710493493560c0c223c49f20"}, ] [package.dependencies] @@ -3392,6 +3385,7 @@ brotlicffi = {version = ">=0.8.0", optional = true, markers = "platform_python_i [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)"] @@ -3587,4 +3581,4 @@ virustotal = ["validators"] [metadata] lock-version = "2.0" python-versions = "^3.8" -content-hash = "fe53909337a8385381a72ee1b604ceaa0555946014ee34b5f1db4571d46299a1" +content-hash = "8a8f5f6d17bf8b927917f138ec3c0148911f34f6588812efade205852690dd9e" diff --git a/pyproject.toml b/pyproject.toml index cc9dd58..f5b9876 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -53,7 +53,7 @@ pydeep2 = {version = "^0.5.1", optional = true} lief = {version = "^0.14", optional = true} beautifulsoup4 = {version = "^4.12.3", optional = true} validators = {version = "^0.22.0", optional = true} -sphinx-autodoc-typehints = {version = "^1.25.2", optional = true} +sphinx-autodoc-typehints = {version = "^1.25.3", optional = true} recommonmark = {version = "^0.7.1", optional = true} reportlab = {version = "^4.0.9", optional = true} pyfaup = {version = "^1.2", optional = true} @@ -82,8 +82,8 @@ ipython = [ {version = "^8.18.0", python = ">=3.9"}, {version = "^8.19.0", python = ">=3.10"} ] -jupyterlab = "^4.0.11" -types-requests = "^2.31.0.20240106" +jupyterlab = "^4.0.12" +types-requests = "^2.31.0.20240125" types-python-dateutil = "^2.8.19.20240106" types-redis = "^4.6.0.20240106" types-Flask = "^1.1.6" From 8fb34a289200db0dd9fce436395344c334e0d54e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Vinot?= Date: Thu, 1 Feb 2024 14:56:57 +0100 Subject: [PATCH 54/80] fix: Import FileObject as needed. --- pymisp/tools/create_misp_object.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pymisp/tools/create_misp_object.py b/pymisp/tools/create_misp_object.py index 2efcb90..0ccacf9 100644 --- a/pymisp/tools/create_misp_object.py +++ b/pymisp/tools/create_misp_object.py @@ -19,6 +19,7 @@ try: from .peobject import make_pe_objects from .elfobject import make_elf_objects from .machoobject import make_macho_objects + from . import FileObject except AttributeError: HAS_LIEF = False @@ -28,7 +29,7 @@ except ImportError: HAS_LIEF = False if TYPE_CHECKING: - from . import FileObject, PEObject, ELFObject, MachOObject, PESectionObject, ELFSectionObject, MachOSectionObject + from . import PEObject, ELFObject, MachOObject, PESectionObject, ELFSectionObject, MachOSectionObject class FileTypeNotImplemented(MISPObjectException): From c3a3868f4207038936e8b3ab846cd107394df65e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Vinot?= Date: Thu, 1 Feb 2024 15:32:00 +0100 Subject: [PATCH 55/80] fix: handle list responses properly --- pymisp/api.py | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/pymisp/api.py b/pymisp/api.py index d19a0ba..76e6880 100644 --- a/pymisp/api.py +++ b/pymisp/api.py @@ -718,10 +718,10 @@ class PyMISP: r = self._prepare_request('GET', f'objectTemplates/getRaw/{uuid_or_name}') return self._check_json_response(r) - def update_object_templates(self) -> dict[str, Any]: + def update_object_templates(self) -> dict[str, Any] | list[dict[str, Any]]: """Trigger an update of the object templates""" response = self._prepare_request('POST', 'objectTemplates/update') - return self._check_json_response(response) + return self._check_json_response_list(response) # ## END Object ### @@ -1202,7 +1202,7 @@ class PyMISP: response = self._prepare_request('POST', f'taxonomies/enable/{taxonomy_id}') return self._check_json_response(response) - def disable_taxonomy(self, taxonomy: MISPTaxonomy | int | str | UUID) -> dict[str, Any]: + def disable_taxonomy(self, taxonomy: MISPTaxonomy | int | str | UUID) -> dict[str, Any] | list[dict[str, Any]]: """Disable a taxonomy: https://www.misp-project.org/openapi/#tag/Taxonomies/operation/disableTaxonomy :param taxonomy: taxonomy to disable @@ -1238,10 +1238,10 @@ class PyMISP: response = self._prepare_request('POST', url) return self._check_json_response(response) - def update_taxonomies(self) -> dict[str, Any]: + def update_taxonomies(self) -> dict[str, Any] | list[dict[str, Any]]: """Update all the taxonomies: https://www.misp-project.org/openapi/#tag/Taxonomies/operation/updateTaxonomies""" response = self._prepare_request('POST', 'taxonomies/update') - return self._check_json_response(response) + return self._check_json_response_list(response) def set_taxonomy_required(self, taxonomy: MISPTaxonomy | int | str, required: bool = False) -> dict[str, Any]: taxonomy_id = get_uuid_or_id_from_abstract_misp(taxonomy) @@ -1330,18 +1330,18 @@ class PyMISP: warninglist_id = get_uuid_or_id_from_abstract_misp(warninglist) return self.toggle_warninglist(warninglist_id=warninglist_id, force_enable=False) - def values_in_warninglist(self, value: Iterable[str]) -> dict[str, Any]: + def values_in_warninglist(self, value: Iterable[str]) -> dict[str, Any] | list[dict[str, Any]]: """Check if IOC values are in warninglist :param value: iterator with values to check """ response = self._prepare_request('POST', 'warninglists/checkValue', data=value) - return self._check_json_response(response) + return self._check_json_response_list(response) - def update_warninglists(self) -> dict[str, Any]: + def update_warninglists(self) -> dict[str, Any] | list[dict[str, Any]]: """Update all the warninglists: https://www.misp-project.org/openapi/#tag/Warninglists/operation/updateWarninglists""" response = self._prepare_request('POST', 'warninglists/update') - return self._check_json_response(response) + return self._check_json_response_list(response) # ## END Warninglists ### @@ -1400,10 +1400,10 @@ class PyMISP: response = self._prepare_request('POST', f'noticelists/enableNoticelist/{noticelist_id}') return self._check_json_response(response) - def update_noticelists(self) -> dict[str, Any]: + def update_noticelists(self) -> dict[str, Any] | list[dict[str, Any]]: """Update all the noticelists: https://www.misp-project.org/openapi/#tag/Noticelists/operation/updateNoticelists""" response = self._prepare_request('POST', 'noticelists/update') - return self._check_json_response(response) + return self._check_json_response_list(response) # ## END Noticelist ### @@ -1553,10 +1553,10 @@ class PyMISP: response.append(c) return response - def update_galaxies(self) -> dict[str, Any]: + def update_galaxies(self) -> dict[str, Any] | list[dict[str, Any]]: """Update all the galaxies: https://www.misp-project.org/openapi/#tag/Galaxies/operation/updateGalaxies""" response = self._prepare_request('POST', 'galaxies/update') - return self._check_json_response(response) + return self._check_json_response_list(response) def get_galaxy_cluster(self, galaxy_cluster: MISPGalaxyCluster | int | str | UUID, pythonify: bool = False) -> dict[str, Any] | MISPGalaxyCluster: """Gets a specific galaxy cluster @@ -2475,10 +2475,10 @@ class PyMISP: # ## BEGIN Decaying Models ### - def update_decaying_models(self) -> dict[str, Any]: + def update_decaying_models(self) -> dict[str, Any] | list[dict[str, Any]]: """Update all the Decaying models""" response = self._prepare_request('POST', 'decayingModel/update') - return self._check_json_response(response) + return self._check_json_response_list(response) def decaying_models(self, pythonify: bool = False) -> dict[str, Any] | list[MISPDecayingModel] | list[dict[str, Any]]: """Get all the decaying models From b5b4a5ef52969f6615c8ef8a371f15ed43cd8687 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Vinot?= Date: Thu, 1 Feb 2024 17:24:24 +0100 Subject: [PATCH 56/80] fix: More fixes to support responses from MISP --- pymisp/api.py | 58 +++++++++++++++++++-------------- pymisp/mispevent.py | 2 +- pymisp/tools/peobject.py | 3 +- tests/testlive_comprehensive.py | 2 +- 4 files changed, 38 insertions(+), 27 deletions(-) diff --git a/pymisp/api.py b/pymisp/api.py index 76e6880..d7046eb 100644 --- a/pymisp/api.py +++ b/pymisp/api.py @@ -243,13 +243,13 @@ class PyMISP: self.category_type_mapping = self.describe_types['category_type_mappings'] self.sane_default = self.describe_types['sane_defaults'] - def remote_acl(self, debug_type: str = 'findMissingFunctionNames') -> dict[str, Any]: + def remote_acl(self, debug_type: str = 'findMissingFunctionNames') -> dict[str, Any] | list[dict[str, Any]]: """This should return an empty list, unless the ACL is outdated. :param debug_type: printAllFunctionNames, findMissingFunctionNames, or printRoleAccess """ response = self._prepare_request('GET', f'events/queryACL/{debug_type}') - return self._check_json_response(response) + return self._check_json_response_list(response) @property def describe_types_local(self) -> dict[str, Any]: @@ -1210,16 +1210,19 @@ class PyMISP: taxonomy_id = get_uuid_or_id_from_abstract_misp(taxonomy) self.disable_taxonomy_tags(taxonomy_id) response = self._prepare_request('POST', f'taxonomies/disable/{taxonomy_id}') - return self._check_json_response(response) + try: + return self._check_json_response(response) + except PyMISPError: + return self._check_json_response_list(response) - def disable_taxonomy_tags(self, taxonomy: MISPTaxonomy | int | str | UUID) -> dict[str, Any]: + def disable_taxonomy_tags(self, taxonomy: MISPTaxonomy | int | str | UUID) -> dict[str, Any] | list[dict[str, Any]]: """Disable all the tags of a taxonomy :param taxonomy: taxonomy with tags to disable """ taxonomy_id = get_uuid_or_id_from_abstract_misp(taxonomy) response = self._prepare_request('POST', f'taxonomies/disableTag/{taxonomy_id}') - return self._check_json_response(response) + return self._check_json_response_list(response) def enable_taxonomy_tags(self, taxonomy: MISPTaxonomy | int | str | UUID) -> dict[str, Any]: """Enable all the tags of a taxonomy. NOTE: this is automatically done when you call enable_taxonomy @@ -1238,10 +1241,10 @@ class PyMISP: response = self._prepare_request('POST', url) return self._check_json_response(response) - def update_taxonomies(self) -> dict[str, Any] | list[dict[str, Any]]: + def update_taxonomies(self) -> dict[str, Any]: """Update all the taxonomies: https://www.misp-project.org/openapi/#tag/Taxonomies/operation/updateTaxonomies""" response = self._prepare_request('POST', 'taxonomies/update') - return self._check_json_response_list(response) + return self._check_json_response(response) def set_taxonomy_required(self, taxonomy: MISPTaxonomy | int | str, required: bool = False) -> dict[str, Any]: taxonomy_id = get_uuid_or_id_from_abstract_misp(taxonomy) @@ -1330,18 +1333,18 @@ class PyMISP: warninglist_id = get_uuid_or_id_from_abstract_misp(warninglist) return self.toggle_warninglist(warninglist_id=warninglist_id, force_enable=False) - def values_in_warninglist(self, value: Iterable[str]) -> dict[str, Any] | list[dict[str, Any]]: + def values_in_warninglist(self, value: Iterable[str]) -> dict[str, Any]: """Check if IOC values are in warninglist :param value: iterator with values to check """ response = self._prepare_request('POST', 'warninglists/checkValue', data=value) - return self._check_json_response_list(response) + return self._check_json_response(response) - def update_warninglists(self) -> dict[str, Any] | list[dict[str, Any]]: + def update_warninglists(self) -> dict[str, Any]: """Update all the warninglists: https://www.misp-project.org/openapi/#tag/Warninglists/operation/updateWarninglists""" response = self._prepare_request('POST', 'warninglists/update') - return self._check_json_response_list(response) + return self._check_json_response(response) # ## END Warninglists ### @@ -1400,10 +1403,10 @@ class PyMISP: response = self._prepare_request('POST', f'noticelists/enableNoticelist/{noticelist_id}') return self._check_json_response(response) - def update_noticelists(self) -> dict[str, Any] | list[dict[str, Any]]: + def update_noticelists(self) -> dict[str, Any]: """Update all the noticelists: https://www.misp-project.org/openapi/#tag/Noticelists/operation/updateNoticelists""" response = self._prepare_request('POST', 'noticelists/update') - return self._check_json_response_list(response) + return self._check_json_response(response) # ## END Noticelist ### @@ -1553,10 +1556,10 @@ class PyMISP: response.append(c) return response - def update_galaxies(self) -> dict[str, Any] | list[dict[str, Any]]: + def update_galaxies(self) -> dict[str, Any]: """Update all the galaxies: https://www.misp-project.org/openapi/#tag/Galaxies/operation/updateGalaxies""" response = self._prepare_request('POST', 'galaxies/update') - return self._check_json_response_list(response) + return self._check_json_response(response) def get_galaxy_cluster(self, galaxy_cluster: MISPGalaxyCluster | int | str | UUID, pythonify: bool = False) -> dict[str, Any] | MISPGalaxyCluster: """Gets a specific galaxy cluster @@ -1867,10 +1870,10 @@ class PyMISP: response = self._prepare_request('GET', 'feeds/cacheFeeds/misp') return self._check_json_response(response) - def compare_feeds(self) -> dict[str, Any]: + def compare_feeds(self) -> dict[str, Any] | list[dict[str, Any]]: """Generate the comparison matrix for all the MISP feeds""" response = self._prepare_request('GET', 'feeds/compareFeeds') - return self._check_json_response(response) + return self._check_json_response_list(response) def load_default_feeds(self) -> dict[str, Any]: """Load all the default feeds.""" @@ -2475,10 +2478,10 @@ class PyMISP: # ## BEGIN Decaying Models ### - def update_decaying_models(self) -> dict[str, Any] | list[dict[str, Any]]: + def update_decaying_models(self) -> dict[str, Any]: """Update all the Decaying models""" response = self._prepare_request('POST', 'decayingModel/update') - return self._check_json_response_list(response) + return self._check_json_response(response) def decaying_models(self, pythonify: bool = False) -> dict[str, Any] | list[MISPDecayingModel] | list[dict[str, Any]]: """Get all the decaying models @@ -2731,8 +2734,12 @@ class PyMISP: elif return_format not in ['json', 'yara-json']: return self._check_response(response) - # This one is truly fucked: event returns a list, attributes doesn't. - normalized_response = self._check_json_response(response) + normalized_response: list[dict[str, Any]] | dict[str, Any] + if controller in ['events', 'objects']: + # This one is truly fucked: event returns a list, attributes doesn't. + normalized_response = self._check_json_response_list(response) + elif controller == 'attributes': + normalized_response = self._check_json_response(response) if 'errors' in normalized_response: return normalized_response @@ -2749,7 +2756,7 @@ class PyMISP: to_return.append(me) elif controller == 'attributes': # FIXME: obvs, this is hurting my soul. We need something generic. - for a in normalized_response['Attribute']: + for a in normalized_response['Attribute']: # type: ignore[call-overload] ma = MISPAttribute() ma.from_dict(**a) if 'Event' in ma: @@ -3298,7 +3305,7 @@ class PyMISP: response = self._prepare_request('GET', f'tags/tagStatistics/{p}/{ns}') return self._check_json_response(response) - def users_statistics(self, context: str = 'data') -> dict[str, Any]: + def users_statistics(self, context: str = 'data') -> dict[str, Any] | list[dict[str, Any]]: """Get user statistics from the MISP instance :param context: one of 'data', 'orgs', 'users', 'tags', 'attributehistogram', 'sightings', 'galaxyMatrix' @@ -3307,7 +3314,10 @@ class PyMISP: if context not in availables_contexts: raise PyMISPError("context can only be {','.join(availables_contexts)}") response = self._prepare_request('GET', f'users/statistics/{context}') - return self._check_json_response(response) + try: + return self._check_json_response_list(response) + except PyMISPError: + return self._check_json_response(response) # ## END Statistics ### diff --git a/pymisp/mispevent.py b/pymisp/mispevent.py index a283201..9bab316 100644 --- a/pymisp/mispevent.py +++ b/pymisp/mispevent.py @@ -2007,7 +2007,7 @@ class MISPEvent(AbstractMISP): :param object_id: ID or UUID """ for o in self.objects: - if ((hasattr(o, 'id') and int(o.id) == int(object_id)) + if ((hasattr(o, 'id') and object_id.isdigit() and int(o.id) == int(object_id)) or (hasattr(o, 'uuid') and o.uuid == object_id)): o.delete() break diff --git a/pymisp/tools/peobject.py b/pymisp/tools/peobject.py index e83bbb3..08f35cf 100644 --- a/pymisp/tools/peobject.py +++ b/pymisp/tools/peobject.py @@ -16,6 +16,7 @@ from .abstractgenerator import AbstractMISPObjectGenerator from ..exceptions import InvalidMISPObject import lief +import lief.PE try: import pydeep # type: ignore @@ -201,7 +202,7 @@ class PESigners(AbstractMISPObjectGenerator): self.add_attribute('digest_algorithm', value=str(self.__signer.digest_algorithm)) self.add_attribute('encryption_algorithm', value=str(self.__signer.encryption_algorithm)) self.add_attribute('digest-base64', value=b64encode(self.__signer.encrypted_digest)) - info: lief.PE.SpcSpOpusInfo = self.__signer.get_attribute(lief.PE.SIG_ATTRIBUTE_TYPES.SPC_SP_OPUS_INFO) # type: ignore[attr-defined, assignment] + info: lief.PE.SpcSpOpusInfo = self.__signer.get_attribute(lief.PE.Attribute.TYPE.SPC_SP_OPUS_INFO) # type: ignore[assignment] if info: self.add_attribute('program-name', value=info.program_name) self.add_attribute('url', value=info.more_info) diff --git a/tests/testlive_comprehensive.py b/tests/testlive_comprehensive.py index e2b7198..341784e 100644 --- a/tests/testlive_comprehensive.py +++ b/tests/testlive_comprehensive.py @@ -12,7 +12,7 @@ import unittest from datetime import datetime, timedelta, date, timezone from io import BytesIO from pathlib import Path -from typing import TypeVar, Type, Any +from typing import TypeVar, Any from uuid import uuid4 import urllib3 From 7a12b1f36249ccdb8e1f91692b4edcce1f5aa20b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 1 Feb 2024 16:52:24 +0000 Subject: [PATCH 57/80] build(deps): bump codecov/codecov-action from 3 to 4 Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 3 to 4. - [Release notes](https://github.com/codecov/codecov-action/releases) - [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/codecov/codecov-action/compare/v3...v4) --- updated-dependencies: - dependency-name: codecov/codecov-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/pytest.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pytest.yml b/.github/workflows/pytest.yml index 7ee00e4..8e155b4 100644 --- a/.github/workflows/pytest.yml +++ b/.github/workflows/pytest.yml @@ -42,4 +42,4 @@ jobs: poetry run pytest --cov=pymisp tests/test_*.py - name: Upload coverage to Codecov - uses: codecov/codecov-action@v3 + uses: codecov/codecov-action@v4 From 979d2ee155b61cc8075668b06d56f64609ab237e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Vinot?= Date: Fri, 2 Feb 2024 10:33:11 +0100 Subject: [PATCH 58/80] chg: Add some debug for gha --- tests/testlive_comprehensive.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/testlive_comprehensive.py b/tests/testlive_comprehensive.py index 341784e..cb34dc7 100644 --- a/tests/testlive_comprehensive.py +++ b/tests/testlive_comprehensive.py @@ -1704,7 +1704,9 @@ class TestComprehensive(unittest.TestCase): def test_add_event_with_attachment(self) -> None: first = self.create_simple_event() try: + print(first) first = self.user_misp_connector.add_event(first) + self.assertTrue(isinstance(first, MISPEvent), first) file_obj, bin_obj, sections = make_binary_objects('tests/viper-test-files/test_files/whoami.exe', standalone=False) first.add_object(file_obj) first.add_object(bin_obj) From 5301ddd1facbbf14cbfd805f9bcac38e5dbd1487 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Vinot?= Date: Fri, 2 Feb 2024 10:59:31 +0100 Subject: [PATCH 59/80] chg: Add even more debug for gha --- pymisp/abstract.py | 2 +- tests/testlive_comprehensive.py | 7 +++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/pymisp/abstract.py b/pymisp/abstract.py index 8ca7cae..068e1a5 100644 --- a/pymisp/abstract.py +++ b/pymisp/abstract.py @@ -46,7 +46,7 @@ class MISPFileCache: return data -class Distribution(IntEnum): +class Distribution(Enum): your_organisation_only = 0 this_community_only = 1 connected_communities = 2 diff --git a/tests/testlive_comprehensive.py b/tests/testlive_comprehensive.py index cb34dc7..67f6d2b 100644 --- a/tests/testlive_comprehensive.py +++ b/tests/testlive_comprehensive.py @@ -1702,11 +1702,10 @@ class TestComprehensive(unittest.TestCase): self.admin_misp_connector.delete_event(first) def test_add_event_with_attachment(self) -> None: - first = self.create_simple_event() + first_send = self.create_simple_event() try: - print(first) - first = self.user_misp_connector.add_event(first) - self.assertTrue(isinstance(first, MISPEvent), first) + first = self.user_misp_connector.add_event(first_send) + self.assertTrue(isinstance(first, MISPEvent), '\n'.join([first_send, first])) file_obj, bin_obj, sections = make_binary_objects('tests/viper-test-files/test_files/whoami.exe', standalone=False) first.add_object(file_obj) first.add_object(bin_obj) From 176eed77bfbd30ddffce58744c0e5028d6c53835 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Vinot?= Date: Fri, 2 Feb 2024 11:20:39 +0100 Subject: [PATCH 60/80] chg: remove IntEnum --- pymisp/abstract.py | 4 ++-- tests/testlive_comprehensive.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pymisp/abstract.py b/pymisp/abstract.py index 068e1a5..41b335a 100644 --- a/pymisp/abstract.py +++ b/pymisp/abstract.py @@ -55,14 +55,14 @@ class Distribution(Enum): inherit = 5 -class ThreatLevel(IntEnum): +class ThreatLevel(Enum): high = 1 medium = 2 low = 3 undefined = 4 -class Analysis(IntEnum): +class Analysis(Enum): initial = 0 ongoing = 1 completed = 2 diff --git a/tests/testlive_comprehensive.py b/tests/testlive_comprehensive.py index 67f6d2b..036cf3a 100644 --- a/tests/testlive_comprehensive.py +++ b/tests/testlive_comprehensive.py @@ -1705,7 +1705,7 @@ class TestComprehensive(unittest.TestCase): first_send = self.create_simple_event() try: first = self.user_misp_connector.add_event(first_send) - self.assertTrue(isinstance(first, MISPEvent), '\n'.join([first_send, first])) + self.assertTrue(isinstance(first, MISPEvent), first) file_obj, bin_obj, sections = make_binary_objects('tests/viper-test-files/test_files/whoami.exe', standalone=False) first.add_object(file_obj) first.add_object(bin_obj) From b00ae036553338de146c70d1eb3b6d99c82d9920 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Vinot?= Date: Fri, 2 Feb 2024 11:38:37 +0100 Subject: [PATCH 61/80] fix: Do not cast enum --- tests/testlive_comprehensive.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/testlive_comprehensive.py b/tests/testlive_comprehensive.py index 036cf3a..e741acc 100644 --- a/tests/testlive_comprehensive.py +++ b/tests/testlive_comprehensive.py @@ -135,8 +135,8 @@ class TestComprehensive(unittest.TestCase): mispevent = MISPEvent(force_timestamps=force_timestamps) mispevent.info = 'This is a super simple test' mispevent.distribution = Distribution.your_organisation_only - mispevent.threat_level_id = int(ThreatLevel.low) - mispevent.analysis = int(Analysis.completed) + mispevent.threat_level_id = ThreatLevel.low + mispevent.analysis = Analysis.completed mispevent.add_attribute('text', str(uuid4())) return mispevent From e91a7922a74cf8f407ee251845ac804e9d25b95f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Vinot?= Date: Fri, 2 Feb 2024 13:06:49 +0100 Subject: [PATCH 62/80] fix: another call that cn be a list or a dict. --- pymisp/api.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/pymisp/api.py b/pymisp/api.py index d7046eb..3537a7d 100644 --- a/pymisp/api.py +++ b/pymisp/api.py @@ -1333,13 +1333,16 @@ class PyMISP: warninglist_id = get_uuid_or_id_from_abstract_misp(warninglist) return self.toggle_warninglist(warninglist_id=warninglist_id, force_enable=False) - def values_in_warninglist(self, value: Iterable[str]) -> dict[str, Any]: + def values_in_warninglist(self, value: Iterable[str]) -> dict[str, Any] | list[dict[str, Any]]: """Check if IOC values are in warninglist :param value: iterator with values to check """ response = self._prepare_request('POST', 'warninglists/checkValue', data=value) - return self._check_json_response(response) + try: + return self._check_json_response_list(response) + except PyMISPError: + return self._check_json_response(response) def update_warninglists(self) -> dict[str, Any]: """Update all the warninglists: https://www.misp-project.org/openapi/#tag/Warninglists/operation/updateWarninglists""" From 709a10c64c0513b515f25c3ecfb9eb577b55084b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Vinot?= Date: Fri, 2 Feb 2024 13:24:29 +0100 Subject: [PATCH 63/80] fix: More responses athat are lists --- pymisp/api.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pymisp/api.py b/pymisp/api.py index 3537a7d..c674049 100644 --- a/pymisp/api.py +++ b/pymisp/api.py @@ -3515,14 +3515,14 @@ class PyMISP: o.from_dict(**updated_organisation_blocklist) return o - def delete_event_blocklist(self, event_blocklist: MISPEventBlocklist | str | UUID) -> dict[str, Any]: + def delete_event_blocklist(self, event_blocklist: MISPEventBlocklist | str | UUID) -> dict[str, Any] | list[dict[str, Any]]: """Delete a blocklisted event by id :param event_blocklist: event block list to delete """ event_blocklist_id = get_uuid_or_id_from_abstract_misp(event_blocklist) response = self._prepare_request('POST', f'eventBlocklists/delete/{event_blocklist_id}') - return self._check_json_response(response) + return self._check_json_response_list(response) def delete_organisation_blocklist(self, organisation_blocklist: MISPOrganisationBlocklist | str | UUID) -> dict[str, Any]: """Delete a blocklisted organisation by id From 9d4d083e466646b9bf0ee0de8b313c3550b08945 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Vinot?= Date: Fri, 2 Feb 2024 14:28:04 +0100 Subject: [PATCH 64/80] Revert "fix: More responses athat are lists" This reverts commit 709a10c64c0513b515f25c3ecfb9eb577b55084b. --- pymisp/api.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pymisp/api.py b/pymisp/api.py index c674049..3537a7d 100644 --- a/pymisp/api.py +++ b/pymisp/api.py @@ -3515,14 +3515,14 @@ class PyMISP: o.from_dict(**updated_organisation_blocklist) return o - def delete_event_blocklist(self, event_blocklist: MISPEventBlocklist | str | UUID) -> dict[str, Any] | list[dict[str, Any]]: + def delete_event_blocklist(self, event_blocklist: MISPEventBlocklist | str | UUID) -> dict[str, Any]: """Delete a blocklisted event by id :param event_blocklist: event block list to delete """ event_blocklist_id = get_uuid_or_id_from_abstract_misp(event_blocklist) response = self._prepare_request('POST', f'eventBlocklists/delete/{event_blocklist_id}') - return self._check_json_response_list(response) + return self._check_json_response(response) def delete_organisation_blocklist(self, organisation_blocklist: MISPOrganisationBlocklist | str | UUID) -> dict[str, Any]: """Delete a blocklisted organisation by id From 685ef22d0a1123c518093fba14dd2c1a0d153ad0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Vinot?= Date: Fri, 2 Feb 2024 15:05:15 +0100 Subject: [PATCH 65/80] fix: revert typing changes. --- mypy.ini | 3 +- pymisp/api.py | 267 ++++++++++++++++++++++++-------------------------- 2 files changed, 131 insertions(+), 139 deletions(-) diff --git a/mypy.ini b/mypy.ini index b4fb74d..3f7aec0 100644 --- a/mypy.ini +++ b/mypy.ini @@ -6,8 +6,9 @@ pretty = True exclude = tests/testlive_comprehensive.py|tests/testlive_sync.py|feed-generator|examples|pymisp/data|docs|pymisp/tools/openioc.py|pymisp/tools/reportlab_generator.py|tests/test_reportlab.py # Stuff to remove gradually -# disallow_untyped_defs = False +disallow_untyped_defs = False disallow_untyped_calls = False +disable_error_code = arg-type,return-value,assignment,call-overload,union-attr [mypy-docs.source.*] diff --git a/pymisp/api.py b/pymisp/api.py index 3537a7d..ffbb08b 100644 --- a/pymisp/api.py +++ b/pymisp/api.py @@ -100,7 +100,7 @@ def register_user(misp_url: str, email: str, org_id: str | None = None, org_name: str | None = None, message: str | None = None, custom_perms: str | None = None, perm_sync: bool = False, perm_publish: bool = False, perm_admin: bool = False, - verify: bool = True) -> dict[str, Any]: + verify: bool = True) -> dict[str, Any] | list[dict[str, Any]]: """Ask for the creation of an account for the user with the given email address""" data = copy.deepcopy(locals()) if organisation: @@ -249,22 +249,22 @@ class PyMISP: :param debug_type: printAllFunctionNames, findMissingFunctionNames, or printRoleAccess """ response = self._prepare_request('GET', f'events/queryACL/{debug_type}') - return self._check_json_response_list(response) + return self._check_json_response(response) @property - def describe_types_local(self) -> dict[str, Any]: + def describe_types_local(self) -> dict[str, Any] | list[dict[str, Any]]: '''Returns the content of describe types from the package''' return describe_types @property - def describe_types_remote(self) -> dict[str, Any]: + def describe_types_remote(self) -> dict[str, Any] | list[dict[str, Any]]: '''Returns the content of describe types from the remote instance''' response = self._prepare_request('GET', 'attributes/describeTypes.json') remote_describe_types = self._check_json_response(response) return remote_describe_types['result'] @property - def recommended_pymisp_version(self) -> dict[str, Any]: + def recommended_pymisp_version(self) -> dict[str, Any] | list[dict[str, Any]]: """Returns the recommended API version from the server""" # Sine MISP 2.4.146 is recommended PyMISP version included in getVersion call misp_version = self.misp_instance_version @@ -275,17 +275,17 @@ class PyMISP: return self._check_json_response(response) @property - def version(self) -> dict[str, Any]: + def version(self) -> dict[str, Any] | list[dict[str, Any]]: """Returns the version of PyMISP you're currently using""" return {'version': __version__} @property - def pymisp_version_master(self) -> dict[str, Any]: + def pymisp_version_master(self) -> dict[str, Any] | list[dict[str, Any]]: """PyMISP version as defined in the main repository""" return self.pymisp_version_main @property - def pymisp_version_main(self) -> dict[str, Any]: + def pymisp_version_main(self) -> dict[str, Any] | list[dict[str, Any]]: """Get the most recent version of PyMISP from github""" r = requests.get('https://raw.githubusercontent.com/MISP/PyMISP/main/pyproject.toml') if r.status_code == 200: @@ -294,13 +294,13 @@ class PyMISP: return {'error': 'Impossible to retrieve the version of the main branch.'} @cached_property - def misp_instance_version(self) -> dict[str, Any]: + def misp_instance_version(self) -> dict[str, Any] | list[dict[str, Any]]: """Returns the version of the instance.""" response = self._prepare_request('GET', 'servers/getVersion') return self._check_json_response(response) @property - def misp_instance_version_master(self) -> dict[str, Any]: + def misp_instance_version_master(self) -> dict[str, Any] | list[dict[str, Any]]: """Get the most recent version from github""" r = requests.get('https://raw.githubusercontent.com/MISP/MISP/2.4/VERSION.json') if r.status_code == 200: @@ -308,12 +308,12 @@ class PyMISP: return {'version': '{}.{}.{}'.format(master_version['major'], master_version['minor'], master_version['hotfix'])} return {'error': 'Impossible to retrieve the version of the master branch.'} - def update_misp(self) -> dict[str, Any]: + def update_misp(self) -> dict[str, Any] | list[dict[str, Any]]: """Trigger a server update""" response = self._prepare_request('POST', 'servers/update') return self._check_json_response(response) - def set_server_setting(self, setting: str, value: str | int | bool, force: bool = False) -> dict[str, Any]: + def set_server_setting(self, setting: str, value: str | int | bool, force: bool = False) -> dict[str, Any] | list[dict[str, Any]]: """Set a setting on the MISP instance :param setting: server setting name @@ -324,7 +324,7 @@ class PyMISP: response = self._prepare_request('POST', f'servers/serverSettingsEdit/{setting}', data=data) return self._check_json_response(response) - def get_server_setting(self, setting: str) -> dict[str, Any]: + def get_server_setting(self, setting: str) -> dict[str, Any] | list[dict[str, Any]]: """Get a setting from the MISP instance :param setting: server setting name @@ -332,17 +332,17 @@ class PyMISP: response = self._prepare_request('GET', f'servers/getSetting/{setting}') return self._check_json_response(response) - def server_settings(self) -> dict[str, Any]: + def server_settings(self) -> dict[str, Any] | list[dict[str, Any]]: """Get all the settings from the server""" response = self._prepare_request('GET', 'servers/serverSettings') return self._check_json_response(response) - def restart_workers(self) -> dict[str, Any]: + def restart_workers(self) -> dict[str, Any] | list[dict[str, Any]]: """Restart all the workers""" response = self._prepare_request('POST', 'servers/restartWorkers') return self._check_json_response(response) - def db_schema_diagnostic(self) -> dict[str, Any]: + def db_schema_diagnostic(self) -> dict[str, Any] | list[dict[str, Any]]: """Get the schema diagnostic""" response = self._prepare_request('GET', 'servers/dbSchemaDiagnostic') return self._check_json_response(response) @@ -359,7 +359,7 @@ class PyMISP: :param pythonify: Returns a list of PyMISP Objects instead of the plain json output. Warning: it might use a lot of RAM """ r = self._prepare_request('GET', 'events/index') - events_r = self._check_json_response_list(r) + events_r = self._check_json_response(r) if not (self.global_pythonify or pythonify) or isinstance(events_r, dict): return events_r to_return = [] @@ -444,7 +444,7 @@ class PyMISP: e.load(updated_event) return e - def delete_event(self, event: MISPEvent | int | str | UUID) -> dict[str, Any]: + def delete_event(self, event: MISPEvent | int | str | UUID) -> dict[str, Any] | list[dict[str, Any]]: """Delete an event from a MISP instance: https://www.misp-project.org/openapi/#tag/Events/operation/deleteEvent :param event: event to delete @@ -453,7 +453,7 @@ class PyMISP: response = self._prepare_request('POST', f'events/delete/{event_id}') return self._check_json_response(response) - def publish(self, event: MISPEvent | int | str | UUID, alert: bool = False) -> dict[str, Any]: + def publish(self, event: MISPEvent | int | str | UUID, alert: bool = False) -> dict[str, Any] | list[dict[str, Any]]: """Publish the event with one single HTTP POST: https://www.misp-project.org/openapi/#tag/Events/operation/publishEvent :param event: event to publish @@ -466,7 +466,7 @@ class PyMISP: response = self._prepare_request('POST', f'events/publish/{event_id}') return self._check_json_response(response) - def unpublish(self, event: MISPEvent | int | str | UUID) -> dict[str, Any]: + def unpublish(self, event: MISPEvent | int | str | UUID) -> dict[str, Any] | list[dict[str, Any]]: """Unpublish the event with one single HTTP POST: https://www.misp-project.org/openapi/#tag/Events/operation/unpublishEvent :param event: event to unpublish @@ -475,7 +475,7 @@ class PyMISP: response = self._prepare_request('POST', f'events/unpublish/{event_id}') return self._check_json_response(response) - def contact_event_reporter(self, event: MISPEvent | int | str | UUID, message: str) -> dict[str, Any]: + def contact_event_reporter(self, event: MISPEvent | int | str | UUID, message: str) -> dict[str, Any] | list[dict[str, Any]]: """Send a message to the reporter of an event :param event: event with reporter to contact @@ -514,7 +514,7 @@ class PyMISP: :param pythonify: Returns a list of PyMISP Objects instead of the plain json output. """ r = self._prepare_request('GET', f'eventReports/index/event_id:{event_id}') - event_reports = self._check_json_response_list(r) + event_reports = self._check_json_response(r) if not (self.global_pythonify or pythonify) or isinstance(event_reports, dict): return event_reports to_return = [] @@ -559,7 +559,7 @@ class PyMISP: er.from_dict(**updated_event_report) return er - def delete_event_report(self, event_report: MISPEventReport | int | str | UUID, hard: bool = False) -> dict[str, Any]: + def delete_event_report(self, event_report: MISPEventReport | int | str | UUID, hard: bool = False) -> dict[str, Any] | list[dict[str, Any]]: """Delete an event report from a MISP instance :param event_report: event report to delete @@ -638,7 +638,7 @@ class PyMISP: o.from_dict(**updated_object) return o - def delete_object(self, misp_object: MISPObject | int | str | UUID, hard: bool = False) -> dict[str, Any]: + def delete_object(self, misp_object: MISPObject | int | str | UUID, hard: bool = False) -> dict[str, Any] | list[dict[str, Any]]: """Delete an object from a MISP instance: https://www.misp-project.org/openapi/#tag/Objects/operation/deleteObject :param misp_object: object to delete @@ -669,7 +669,7 @@ class PyMISP: self, object_reference: MISPObjectReference | int | str | UUID, hard: bool = False, - ) -> dict[str, Any]: + ) -> dict[str, Any] | list[dict[str, Any]]: """Delete a reference to an object.""" object_reference_id = get_uuid_or_id_from_abstract_misp(object_reference) query_url = f"objectReferences/delete/{object_reference_id}" @@ -686,7 +686,7 @@ class PyMISP: :param pythonify: Returns a list of PyMISP Objects instead of the plain json output. Warning: it might use a lot of RAM """ r = self._prepare_request('GET', 'objectTemplates/index') - templates = self._check_json_response_list(r) + templates = self._check_json_response(r) if not (self.global_pythonify or pythonify) or isinstance(templates, dict): return templates to_return = [] @@ -711,7 +711,7 @@ class PyMISP: t.from_dict(**object_template_r) return t - def get_raw_object_template(self, uuid_or_name: str) -> dict[str, Any]: + def get_raw_object_template(self, uuid_or_name: str) -> dict[str, Any] | list[dict[str, Any]]: """Get a row template. It needs to be present on disk on the MISP instance you're connected to. The response of this method can be passed to MISPObject(, misp_objects_template_custom=) """ @@ -721,7 +721,7 @@ class PyMISP: def update_object_templates(self) -> dict[str, Any] | list[dict[str, Any]]: """Trigger an update of the object templates""" response = self._prepare_request('POST', 'objectTemplates/update') - return self._check_json_response_list(response) + return self._check_json_response(response) # ## END Object ### @@ -733,7 +733,7 @@ class PyMISP: :param pythonify: Returns a list of PyMISP Objects instead of the plain json output. Warning: it might use a lot of RAM """ r = self._prepare_request('GET', 'attributes/index') - attributes_r = self._check_json_response_list(r) + attributes_r = self._check_json_response(r) if not (self.global_pythonify or pythonify) or isinstance(attributes_r, dict): return attributes_r to_return = [] @@ -839,7 +839,7 @@ class PyMISP: a.from_dict(**updated_attribute) return a - def delete_attribute(self, attribute: MISPAttribute | int | str | UUID, hard: bool = False) -> dict[str, Any]: + def delete_attribute(self, attribute: MISPAttribute | int | str | UUID, hard: bool = False) -> dict[str, Any] | list[dict[str, Any]]: """Delete an attribute from a MISP instance: https://www.misp-project.org/openapi/#tag/Attributes/operation/deleteAttribute :param attribute: attribute to delete @@ -888,7 +888,7 @@ class PyMISP: r = self._prepare_request('GET', f'shadowAttributes/index/{event_id}') else: r = self._prepare_request('GET', 'shadowAttributes/index') - attribute_proposals = self._check_json_response_list(r) + attribute_proposals = self._check_json_response(r) if not (self.global_pythonify or pythonify) or isinstance(attribute_proposals, dict): return attribute_proposals to_return = [] @@ -947,7 +947,7 @@ class PyMISP: a.from_dict(**update_attribute_proposal) return a - def delete_attribute_proposal(self, attribute: MISPAttribute | int | str | UUID) -> dict[str, Any]: + def delete_attribute_proposal(self, attribute: MISPAttribute | int | str | UUID) -> dict[str, Any] | list[dict[str, Any]]: """Propose the deletion of an attribute :param attribute: attribute to delete @@ -956,7 +956,7 @@ class PyMISP: response = self._prepare_request('POST', f'shadowAttributes/delete/{attribute_id}') return self._check_json_response(response) - def accept_attribute_proposal(self, proposal: MISPShadowAttribute | int | str | UUID) -> dict[str, Any]: + def accept_attribute_proposal(self, proposal: MISPShadowAttribute | int | str | UUID) -> dict[str, Any] | list[dict[str, Any]]: """Accept a proposal. You cannot modify an existing proposal, only accept/discard :param proposal: attribute proposal to accept @@ -965,7 +965,7 @@ class PyMISP: response = self._prepare_request('POST', f'shadowAttributes/accept/{proposal_id}') return self._check_json_response(response) - def discard_attribute_proposal(self, proposal: MISPShadowAttribute | int | str | UUID) -> dict[str, Any]: + def discard_attribute_proposal(self, proposal: MISPShadowAttribute | int | str | UUID) -> dict[str, Any] | list[dict[str, Any]]: """Discard a proposal. You cannot modify an existing proposal, only accept/discard :param proposal: attribute proposal to discard @@ -1002,7 +1002,7 @@ class PyMISP: to_post['org_id'] = org_id r = self._prepare_request('POST', url, data=to_post) - sightings = self._check_json_response_list(r) + sightings = self._check_json_response(r) if not (self.global_pythonify or pythonify) or isinstance(sightings, dict): return sightings to_return = [] @@ -1034,7 +1034,7 @@ class PyMISP: s.from_dict(**new_sighting) return s - def delete_sighting(self, sighting: MISPSighting | int | str | UUID) -> dict[str, Any]: + def delete_sighting(self, sighting: MISPSighting | int | str | UUID) -> dict[str, Any] | list[dict[str, Any]]: """Delete a sighting from a MISP instance: https://www.misp-project.org/openapi/#tag/Sightings/operation/deleteSighting :param sighting: sighting to delete @@ -1131,7 +1131,7 @@ class PyMISP: t.from_dict(**updated_tag) return t - def delete_tag(self, tag: MISPTag | int | str | UUID) -> dict[str, Any]: + def delete_tag(self, tag: MISPTag | int | str | UUID) -> dict[str, Any] | list[dict[str, Any]]: """Delete a tag from a MISP instance: https://www.misp-project.org/openapi/#tag/Tags/operation/deleteTag :param tag: tag to delete @@ -1148,7 +1148,7 @@ class PyMISP: """ query = {'tagname': tagname, 'strict_tagname': strict_tagname} response = self._prepare_request('POST', 'tags/search', data=query) - normalized_response = self._check_json_response_list(response) + normalized_response = self._check_json_response(response) if not (self.global_pythonify or pythonify) or isinstance(normalized_response, dict): return normalized_response to_return: list[MISPTag] = [] @@ -1168,7 +1168,7 @@ class PyMISP: :param pythonify: Returns a list of PyMISP Objects instead of the plain json output. Warning: it might use a lot of RAM """ r = self._prepare_request('GET', 'taxonomies/index') - taxonomies = self._check_json_response_list(r) + taxonomies = self._check_json_response(r) if not (self.global_pythonify or pythonify) or isinstance(taxonomies, dict): return taxonomies to_return = [] @@ -1193,7 +1193,7 @@ class PyMISP: t.from_dict(**taxonomy_r) return t - def enable_taxonomy(self, taxonomy: MISPTaxonomy | int | str | UUID) -> dict[str, Any]: + def enable_taxonomy(self, taxonomy: MISPTaxonomy | int | str | UUID) -> dict[str, Any] | list[dict[str, Any]]: """Enable a taxonomy: https://www.misp-project.org/openapi/#tag/Taxonomies/operation/enableTaxonomy :param taxonomy: taxonomy to enable @@ -1213,7 +1213,7 @@ class PyMISP: try: return self._check_json_response(response) except PyMISPError: - return self._check_json_response_list(response) + return self._check_json_response(response) def disable_taxonomy_tags(self, taxonomy: MISPTaxonomy | int | str | UUID) -> dict[str, Any] | list[dict[str, Any]]: """Disable all the tags of a taxonomy @@ -1222,9 +1222,9 @@ class PyMISP: """ taxonomy_id = get_uuid_or_id_from_abstract_misp(taxonomy) response = self._prepare_request('POST', f'taxonomies/disableTag/{taxonomy_id}') - return self._check_json_response_list(response) + return self._check_json_response(response) - def enable_taxonomy_tags(self, taxonomy: MISPTaxonomy | int | str | UUID) -> dict[str, Any]: + def enable_taxonomy_tags(self, taxonomy: MISPTaxonomy | int | str | UUID) -> dict[str, Any] | list[dict[str, Any]]: """Enable all the tags of a taxonomy. NOTE: this is automatically done when you call enable_taxonomy :param taxonomy: taxonomy with tags to enable @@ -1241,12 +1241,12 @@ class PyMISP: response = self._prepare_request('POST', url) return self._check_json_response(response) - def update_taxonomies(self) -> dict[str, Any]: + def update_taxonomies(self) -> dict[str, Any] | list[dict[str, Any]]: """Update all the taxonomies: https://www.misp-project.org/openapi/#tag/Taxonomies/operation/updateTaxonomies""" response = self._prepare_request('POST', 'taxonomies/update') return self._check_json_response(response) - def set_taxonomy_required(self, taxonomy: MISPTaxonomy | int | str, required: bool = False) -> dict[str, Any]: + def set_taxonomy_required(self, taxonomy: MISPTaxonomy | int | str, required: bool = False) -> dict[str, Any] | list[dict[str, Any]]: taxonomy_id = get_uuid_or_id_from_abstract_misp(taxonomy) url = urljoin(self.root_url, f'taxonomies/toggleRequired/{taxonomy_id}') payload = { @@ -1292,7 +1292,7 @@ class PyMISP: w.from_dict(**wl) return w - def toggle_warninglist(self, warninglist_id: str | int | list[int] | None = None, warninglist_name: str | list[str] | None = None, force_enable: bool = False) -> dict[str, Any]: + def toggle_warninglist(self, warninglist_id: str | int | list[int] | None = None, warninglist_name: str | list[str] | None = None, force_enable: bool = False) -> dict[str, Any] | list[dict[str, Any]]: '''Toggle (enable/disable) the status of a warninglist by id: https://www.misp-project.org/openapi/#tag/Warninglists/operation/toggleEnableWarninglist :param warninglist_id: ID of the WarningList @@ -1317,7 +1317,7 @@ class PyMISP: response = self._prepare_request('POST', 'warninglists/toggleEnable', data=query) return self._check_json_response(response) - def enable_warninglist(self, warninglist: MISPWarninglist | int | str | UUID) -> dict[str, Any]: + def enable_warninglist(self, warninglist: MISPWarninglist | int | str | UUID) -> dict[str, Any] | list[dict[str, Any]]: """Enable a warninglist :param warninglist: warninglist to enable @@ -1325,7 +1325,7 @@ class PyMISP: warninglist_id = get_uuid_or_id_from_abstract_misp(warninglist) return self.toggle_warninglist(warninglist_id=warninglist_id, force_enable=True) - def disable_warninglist(self, warninglist: MISPWarninglist | int | str | UUID) -> dict[str, Any]: + def disable_warninglist(self, warninglist: MISPWarninglist | int | str | UUID) -> dict[str, Any] | list[dict[str, Any]]: """Disable a warninglist :param warninglist: warninglist to disable @@ -1340,11 +1340,11 @@ class PyMISP: """ response = self._prepare_request('POST', 'warninglists/checkValue', data=value) try: - return self._check_json_response_list(response) + return self._check_json_response(response) except PyMISPError: return self._check_json_response(response) - def update_warninglists(self) -> dict[str, Any]: + def update_warninglists(self) -> dict[str, Any] | list[dict[str, Any]]: """Update all the warninglists: https://www.misp-project.org/openapi/#tag/Warninglists/operation/updateWarninglists""" response = self._prepare_request('POST', 'warninglists/update') return self._check_json_response(response) @@ -1359,7 +1359,7 @@ class PyMISP: :param pythonify: Returns a list of PyMISP Objects instead of the plain json output. Warning: it might use a lot of RAM """ r = self._prepare_request('GET', 'noticelists/index') - noticelists = self._check_json_response_list(r) + noticelists = self._check_json_response(r) if not (self.global_pythonify or pythonify) or isinstance(noticelists, dict): return noticelists to_return = [] @@ -1384,7 +1384,7 @@ class PyMISP: n.from_dict(**noticelist_j) return n - def enable_noticelist(self, noticelist: MISPNoticelist | int | str | UUID) -> dict[str, Any]: + def enable_noticelist(self, noticelist: MISPNoticelist | int | str | UUID) -> dict[str, Any] | list[dict[str, Any]]: """Enable a noticelist by id: https://www.misp-project.org/openapi/#tag/Noticelists/operation/toggleEnableNoticelist :param noticelist: Noticelist to enable @@ -1395,7 +1395,7 @@ class PyMISP: response = self._prepare_request('POST', f'noticelists/enableNoticelist/{noticelist_id}/true') return self._check_json_response(response) - def disable_noticelist(self, noticelist: MISPNoticelist | int | str | UUID) -> dict[str, Any]: + def disable_noticelist(self, noticelist: MISPNoticelist | int | str | UUID) -> dict[str, Any] | list[dict[str, Any]]: """Disable a noticelist by id :param noticelist: Noticelist to disable @@ -1406,7 +1406,7 @@ class PyMISP: response = self._prepare_request('POST', f'noticelists/enableNoticelist/{noticelist_id}') return self._check_json_response(response) - def update_noticelists(self) -> dict[str, Any]: + def update_noticelists(self) -> dict[str, Any] | list[dict[str, Any]]: """Update all the noticelists: https://www.misp-project.org/openapi/#tag/Noticelists/operation/updateNoticelists""" response = self._prepare_request('POST', 'noticelists/update') return self._check_json_response(response) @@ -1421,7 +1421,7 @@ class PyMISP: :param pythonify: Returns a list of PyMISP Objects instead of the plain json output. Warning: it might use a lot of RAM """ r = self._prepare_request('GET', 'correlation_exclusions') - correlation_exclusions = self._check_json_response_list(r) + correlation_exclusions = self._check_json_response(r) if not (self.global_pythonify or pythonify) or isinstance(correlation_exclusions, dict): return correlation_exclusions to_return = [] @@ -1460,7 +1460,7 @@ class PyMISP: c.from_dict(**new_correlation_exclusion) return c - def delete_correlation_exclusion(self, correlation_exclusion: MISPCorrelationExclusion | int | str | UUID) -> dict[str, Any]: + def delete_correlation_exclusion(self, correlation_exclusion: MISPCorrelationExclusion | int | str | UUID) -> dict[str, Any] | list[dict[str, Any]]: """Delete a correlation exclusion :param correlation_exclusion: The MISPCorrelationExclusion you wish to delete from MISP @@ -1469,7 +1469,7 @@ class PyMISP: r = self._prepare_request('POST', f'correlation_exclusions/delete/{exclusion_id}') return self._check_json_response(r) - def clean_correlation_exclusions(self) -> dict[str, Any]: + def clean_correlation_exclusions(self) -> dict[str, Any] | list[dict[str, Any]]: """Initiate correlation exclusions cleanup""" r = self._prepare_request('POST', 'correlation_exclusions/clean') return self._check_json_response(r) @@ -1488,7 +1488,7 @@ class PyMISP: :param pythonify: Returns a list of PyMISP Objects instead of the plain json output. Warning: it might use a lot of RAM """ r = self._prepare_request('GET', 'galaxies/index') - galaxies = self._check_json_response_list(r) + galaxies = self._check_json_response(r) if not (self.global_pythonify or pythonify) or isinstance(galaxies, dict): return galaxies to_return = [] @@ -1506,7 +1506,7 @@ class PyMISP: ) -> dict[str, Any] | list[MISPGalaxy] | list[dict[str, Any]]: """Text search to find a matching galaxy name, namespace, description, or uuid.""" r = self._prepare_request("POST", "galaxies", data={"value": value}) - galaxies = self._check_json_response_list(r) + galaxies = self._check_json_response(r) if not (self.global_pythonify or pythonify) or isinstance(galaxies, dict): return galaxies to_return = [] @@ -1549,7 +1549,7 @@ class PyMISP: if searchall: kw_params["searchall"] = searchall r = self._prepare_request('POST', f"galaxy_clusters/index/{galaxy_id}", data=kw_params) - clusters_j = self._check_json_response_list(r) + clusters_j = self._check_json_response(r) if not (self.global_pythonify or pythonify) or isinstance(clusters_j, dict): return clusters_j response = [] @@ -1559,7 +1559,7 @@ class PyMISP: response.append(c) return response - def update_galaxies(self) -> dict[str, Any]: + def update_galaxies(self) -> dict[str, Any] | list[dict[str, Any]]: """Update all the galaxies: https://www.misp-project.org/openapi/#tag/Galaxies/operation/updateGalaxies""" response = self._prepare_request('POST', 'galaxies/update') return self._check_json_response(response) @@ -1619,7 +1619,7 @@ class PyMISP: gc.from_dict(**cluster_j) return gc - def publish_galaxy_cluster(self, galaxy_cluster: MISPGalaxyCluster | int | str | UUID) -> dict[str, Any]: + def publish_galaxy_cluster(self, galaxy_cluster: MISPGalaxyCluster | int | str | UUID) -> dict[str, Any] | list[dict[str, Any]]: """Publishes a galaxy cluster: https://www.misp-project.org/openapi/#tag/Galaxy-Clusters/operation/publishGalaxyCluster :param galaxy_cluster: The galaxy cluster you wish to publish @@ -1655,7 +1655,7 @@ class PyMISP: gc.from_dict(**cluster_j) return gc - def delete_galaxy_cluster(self, galaxy_cluster: MISPGalaxyCluster | int | str | UUID, hard: bool=False) -> dict[str, Any]: + def delete_galaxy_cluster(self, galaxy_cluster: MISPGalaxyCluster | int | str | UUID, hard: bool=False) -> dict[str, Any] | list[dict[str, Any]]: """Deletes a galaxy cluster from MISP: https://www.misp-project.org/openapi/#tag/Galaxy-Clusters/operation/deleteGalaxyCluster :param galaxy_cluster: The MISPGalaxyCluster you wish to delete from MISP @@ -1671,7 +1671,7 @@ class PyMISP: r = self._prepare_request('POST', f'galaxy_clusters/delete/{cluster_id}', data=data) return self._check_json_response(r) - def add_galaxy_cluster_relation(self, galaxy_cluster_relation: MISPGalaxyClusterRelation) -> dict[str, Any]: + def add_galaxy_cluster_relation(self, galaxy_cluster_relation: MISPGalaxyClusterRelation) -> dict[str, Any] | list[dict[str, Any]]: """Add a galaxy cluster relation, cluster relation must include cluster UUIDs in both directions @@ -1681,7 +1681,7 @@ class PyMISP: cluster_rel_j = self._check_json_response(r) return cluster_rel_j - def update_galaxy_cluster_relation(self, galaxy_cluster_relation: MISPGalaxyClusterRelation) -> dict[str, Any]: + def update_galaxy_cluster_relation(self, galaxy_cluster_relation: MISPGalaxyClusterRelation) -> dict[str, Any] | list[dict[str, Any]]: """Update a galaxy cluster relation :param galaxy_cluster_relation: The MISPGalaxyClusterRelation to update @@ -1691,7 +1691,7 @@ class PyMISP: cluster_rel_j = self._check_json_response(r) return cluster_rel_j - def delete_galaxy_cluster_relation(self, galaxy_cluster_relation: MISPGalaxyClusterRelation | int | str | UUID) -> dict[str, Any]: + def delete_galaxy_cluster_relation(self, galaxy_cluster_relation: MISPGalaxyClusterRelation | int | str | UUID) -> dict[str, Any] | list[dict[str, Any]]: """Delete a galaxy cluster relation :param galaxy_cluster_relation: The MISPGalaxyClusterRelation to delete @@ -1711,7 +1711,7 @@ class PyMISP: :param pythonify: Returns a list of PyMISP Objects instead of the plain json output. Warning: it might use a lot of RAM """ r = self._prepare_request('GET', 'feeds/index') - feeds = self._check_json_response_list(r) + feeds = self._check_json_response(r) if not (self.global_pythonify or pythonify) or isinstance(feeds, dict): return feeds to_return = [] @@ -1831,7 +1831,7 @@ class PyMISP: f.from_dict(**updated_feed) return f - def delete_feed(self, feed: MISPFeed | int | str | UUID) -> dict[str, Any]: + def delete_feed(self, feed: MISPFeed | int | str | UUID) -> dict[str, Any] | list[dict[str, Any]]: """Delete a feed from a MISP instance :param feed: feed to delete @@ -1840,7 +1840,7 @@ class PyMISP: response = self._prepare_request('POST', f'feeds/delete/{feed_id}') return self._check_json_response(response) - def fetch_feed(self, feed: MISPFeed | int | str | UUID) -> dict[str, Any]: + def fetch_feed(self, feed: MISPFeed | int | str | UUID) -> dict[str, Any] | list[dict[str, Any]]: """Fetch one single feed by id: https://www.misp-project.org/openapi/#tag/Feeds/operation/fetchFromFeed :param feed: feed to fetch @@ -1849,12 +1849,12 @@ class PyMISP: response = self._prepare_request('GET', f'feeds/fetchFromFeed/{feed_id}') return self._check_json_response(response) - def cache_all_feeds(self) -> dict[str, Any]: + def cache_all_feeds(self) -> dict[str, Any] | list[dict[str, Any]]: """ Cache all the feeds: https://www.misp-project.org/openapi/#tag/Feeds/operation/cacheFeeds""" response = self._prepare_request('GET', 'feeds/cacheFeeds/all') return self._check_json_response(response) - def cache_feed(self, feed: MISPFeed | int | str | UUID) -> dict[str, Any]: + def cache_feed(self, feed: MISPFeed | int | str | UUID) -> dict[str, Any] | list[dict[str, Any]]: """Cache a specific feed by id: https://www.misp-project.org/openapi/#tag/Feeds/operation/cacheFeeds :param feed: feed to cache @@ -1863,12 +1863,12 @@ class PyMISP: response = self._prepare_request('GET', f'feeds/cacheFeeds/{feed_id}') return self._check_json_response(response) - def cache_freetext_feeds(self) -> dict[str, Any]: + def cache_freetext_feeds(self) -> dict[str, Any] | list[dict[str, Any]]: """Cache all the freetext feeds""" response = self._prepare_request('GET', 'feeds/cacheFeeds/freetext') return self._check_json_response(response) - def cache_misp_feeds(self) -> dict[str, Any]: + def cache_misp_feeds(self) -> dict[str, Any] | list[dict[str, Any]]: """Cache all the MISP feeds""" response = self._prepare_request('GET', 'feeds/cacheFeeds/misp') return self._check_json_response(response) @@ -1876,9 +1876,9 @@ class PyMISP: def compare_feeds(self) -> dict[str, Any] | list[dict[str, Any]]: """Generate the comparison matrix for all the MISP feeds""" response = self._prepare_request('GET', 'feeds/compareFeeds') - return self._check_json_response_list(response) + return self._check_json_response(response) - def load_default_feeds(self) -> dict[str, Any]: + def load_default_feeds(self) -> dict[str, Any] | list[dict[str, Any]]: """Load all the default feeds.""" response = self._prepare_request('POST', 'feeds/loadDefaultFeeds') return self._check_json_response(response) @@ -1893,7 +1893,7 @@ class PyMISP: :param pythonify: Returns a list of PyMISP Objects instead of the plain json output. Warning: it might use a lot of RAM """ r = self._prepare_request('GET', 'servers/index') - servers = self._check_json_response_list(r) + servers = self._check_json_response(r) if not (self.global_pythonify or pythonify) or isinstance(servers, dict): return servers to_return = [] @@ -1964,7 +1964,7 @@ class PyMISP: s.from_dict(**updated_server) return s - def delete_server(self, server: MISPServer | int | str | UUID) -> dict[str, Any]: + def delete_server(self, server: MISPServer | int | str | UUID) -> dict[str, Any] | list[dict[str, Any]]: """Delete a sync server: https://www.misp-project.org/openapi/#tag/Servers/operation/getServers :param server: sync server config @@ -1973,7 +1973,7 @@ class PyMISP: response = self._prepare_request('POST', f'servers/delete/{server_id}') return self._check_json_response(response) - def server_pull(self, server: MISPServer | int | str | UUID, event: MISPEvent | int | str | UUID | None = None) -> dict[str, Any]: + def server_pull(self, server: MISPServer | int | str | UUID, event: MISPEvent | int | str | UUID | None = None) -> dict[str, Any] | list[dict[str, Any]]: """Initialize a pull from a sync server, optionally limited to one event: https://www.misp-project.org/openapi/#tag/Servers/operation/pullServer :param server: sync server config @@ -1989,7 +1989,7 @@ class PyMISP: # FIXME: can we pythonify? return self._check_json_response(response) - def server_push(self, server: MISPServer | int | str | UUID, event: MISPEvent | int | str | UUID | None = None) -> dict[str, Any]: + def server_push(self, server: MISPServer | int | str | UUID, event: MISPEvent | int | str | UUID | None = None) -> dict[str, Any] | list[dict[str, Any]]: """Initialize a push to a sync server, optionally limited to one event: https://www.misp-project.org/openapi/#tag/Servers/operation/pushServer :param server: sync server config @@ -2005,7 +2005,7 @@ class PyMISP: # FIXME: can we pythonify? return self._check_json_response(response) - def test_server(self, server: MISPServer | int | str | UUID) -> dict[str, Any]: + def test_server(self, server: MISPServer | int | str | UUID) -> dict[str, Any] | list[dict[str, Any]]: """Test if a sync link is working as expected :param server: sync server config @@ -2024,7 +2024,7 @@ class PyMISP: :param pythonify: Returns a list of PyMISP Objects instead of the plain json output. Warning: it might use a lot of RAM """ r = self._prepare_request('GET', 'sharingGroups/index') - sharing_groups = self._check_json_response_list(r) + sharing_groups = self._check_json_response(r) if not (self.global_pythonify or pythonify) or isinstance(sharing_groups, dict): return sharing_groups to_return = [] @@ -2092,7 +2092,7 @@ class PyMISP: r = self._prepare_request('HEAD', f'sharing_groups/view/{sharing_group_id}') return self._check_head_response(r) - def delete_sharing_group(self, sharing_group: MISPSharingGroup | int | str | UUID) -> dict[str, Any]: + def delete_sharing_group(self, sharing_group: MISPSharingGroup | int | str | UUID) -> dict[str, Any] | list[dict[str, Any]]: """Delete a sharing group: https://www.misp-project.org/openapi/#tag/Sharing-Groups/operation/deleteSharingGroup :param sharing_group: sharing group to delete @@ -2102,7 +2102,7 @@ class PyMISP: return self._check_json_response(response) def add_org_to_sharing_group(self, sharing_group: MISPSharingGroup | int | str | UUID, - organisation: MISPOrganisation | int | str | UUID, extend: bool = False) -> dict[str, Any]: + organisation: MISPOrganisation | int | str | UUID, extend: bool = False) -> dict[str, Any] | list[dict[str, Any]]: '''Add an organisation to a sharing group: https://www.misp-project.org/openapi/#tag/Sharing-Groups/operation/addOrganisationToSharingGroup :param sharing_group: Sharing group's local instance ID, or Sharing group's global UUID @@ -2116,7 +2116,7 @@ class PyMISP: return self._check_json_response(response) def remove_org_from_sharing_group(self, sharing_group: MISPSharingGroup | int | str | UUID, - organisation: MISPOrganisation | int | str | UUID) -> dict[str, Any]: + organisation: MISPOrganisation | int | str | UUID) -> dict[str, Any] | list[dict[str, Any]]: '''Remove an organisation from a sharing group: https://www.misp-project.org/openapi/#tag/Sharing-Groups/operation/removeOrganisationFromSharingGroup :param sharing_group: Sharing group's local instance ID, or Sharing group's global UUID @@ -2129,7 +2129,7 @@ class PyMISP: return self._check_json_response(response) def add_server_to_sharing_group(self, sharing_group: MISPSharingGroup | int | str | UUID, - server: MISPServer | int | str | UUID, all_orgs: bool = False) -> dict[str, Any]: + server: MISPServer | int | str | UUID, all_orgs: bool = False) -> dict[str, Any] | list[dict[str, Any]]: '''Add a server to a sharing group: https://www.misp-project.org/openapi/#tag/Sharing-Groups/operation/addServerToSharingGroup :param sharing_group: Sharing group's local instance ID, or Sharing group's global UUID @@ -2143,7 +2143,7 @@ class PyMISP: return self._check_json_response(response) def remove_server_from_sharing_group(self, sharing_group: MISPSharingGroup | int | str | UUID, - server: MISPServer | int | str | UUID) -> dict[str, Any]: + server: MISPServer | int | str | UUID) -> dict[str, Any] | list[dict[str, Any]]: '''Remove a server from a sharing group: https://www.misp-project.org/openapi/#tag/Sharing-Groups/operation/removeServerFromSharingGroup :param sharing_group: Sharing group's local instance ID, or Sharing group's global UUID @@ -2171,7 +2171,7 @@ class PyMISP: url_path += f"/searchall:{search}" r = self._prepare_request('GET', url_path) - organisations = self._check_json_response_list(r) + organisations = self._check_json_response(r) if not (self.global_pythonify or pythonify) or isinstance(organisations, dict): return organisations to_return = [] @@ -2238,7 +2238,7 @@ class PyMISP: o.from_dict(**organisation) return o - def delete_organisation(self, organisation: MISPOrganisation | int | str | UUID) -> dict[str, Any]: + def delete_organisation(self, organisation: MISPOrganisation | int | str | UUID) -> dict[str, Any] | list[dict[str, Any]]: """Delete an organisation by id: https://www.misp-project.org/openapi/#tag/Organisations/operation/deleteOrganisation :param organisation: organization to delete @@ -2266,7 +2266,7 @@ class PyMISP: organisation_id = get_uuid_or_id_from_abstract_misp(organisation) urlpath += f"/searchorg:{organisation_id}" r = self._prepare_request('GET', urlpath) - users = self._check_json_response_list(r) + users = self._check_json_response(r) if not (self.global_pythonify or pythonify) or isinstance(users, dict): return users to_return = [] @@ -2352,7 +2352,7 @@ class PyMISP: e.from_dict(**updated_user) return e - def delete_user(self, user: MISPUser | int | str | UUID) -> dict[str, Any]: + def delete_user(self, user: MISPUser | int | str | UUID) -> dict[str, Any] | list[dict[str, Any]]: """Delete a user by id: https://www.misp-project.org/openapi/#tag/Users/operation/deleteUser :param user: user to delete @@ -2362,7 +2362,7 @@ class PyMISP: response = self._prepare_request('POST', f'admin/users/delete/{user_id}') return self._check_json_response(response) - def change_user_password(self, new_password: str) -> dict[str, Any]: + def change_user_password(self, new_password: str) -> dict[str, Any] | list[dict[str, Any]]: """Change the password of the curent user: :param new_password: password to set @@ -2376,7 +2376,7 @@ class PyMISP: :param pythonify: Returns a list of PyMISP Objects instead of the plain json output. Warning: it might use a lot of RAM """ r = self._prepare_request('GET', 'users/registrations/index') - registrations = self._check_json_response_list(r) + registrations = self._check_json_response(r) if not (self.global_pythonify or pythonify) or isinstance(registrations, dict): return registrations to_return = [] @@ -2391,7 +2391,7 @@ class PyMISP: role: MISPRole | int | str | None = None, perm_sync: bool = False, perm_publish: bool = False, perm_admin: bool = False, - unsafe_fallback: bool = False) -> dict[str, Any]: + unsafe_fallback: bool = False) -> dict[str, Any] | list[dict[str, Any]]: """Accept a user registration :param registration: the registration to accept @@ -2438,7 +2438,7 @@ class PyMISP: r = self._prepare_request('POST', f'users/acceptRegistrations/{registration_id}', data=to_post) return self._check_json_response(r) - def discard_user_registration(self, registration: MISPInbox | int | str | UUID) -> dict[str, Any]: + def discard_user_registration(self, registration: MISPInbox | int | str | UUID) -> dict[str, Any] | list[dict[str, Any]]: """Discard a user registration :param registration: the registration to discard @@ -2457,7 +2457,7 @@ class PyMISP: :param pythonify: Returns a list of PyMISP Objects instead of the plain json output. Warning: it might use a lot of RAM """ r = self._prepare_request('GET', 'roles/index') - roles = self._check_json_response_list(r) + roles = self._check_json_response(r) if not (self.global_pythonify or pythonify) or isinstance(roles, dict): return roles to_return = [] @@ -2467,7 +2467,7 @@ class PyMISP: to_return.append(nr) return to_return - def set_default_role(self, role: MISPRole | int | str | UUID) -> dict[str, Any]: + def set_default_role(self, role: MISPRole | int | str | UUID) -> dict[str, Any] | list[dict[str, Any]]: """Set a default role for the new user accounts :param role: the default role to set @@ -2481,7 +2481,7 @@ class PyMISP: # ## BEGIN Decaying Models ### - def update_decaying_models(self) -> dict[str, Any]: + def update_decaying_models(self) -> dict[str, Any] | list[dict[str, Any]]: """Update all the Decaying models""" response = self._prepare_request('POST', 'decayingModel/update') return self._check_json_response(response) @@ -2492,7 +2492,7 @@ class PyMISP: :param pythonify: Returns a list of PyMISP Objects instead of the plain json output """ r = self._prepare_request('GET', 'decayingModel/index') - models = self._check_json_response_list(r) + models = self._check_json_response(r) if not (self.global_pythonify or pythonify) or isinstance(models, dict): return models to_return = [] @@ -2502,7 +2502,7 @@ class PyMISP: to_return.append(n) return to_return - def enable_decaying_model(self, decaying_model: MISPDecayingModel | int | str) -> dict[str, Any]: + def enable_decaying_model(self, decaying_model: MISPDecayingModel | int | str) -> dict[str, Any] | list[dict[str, Any]]: """Enable a decaying Model""" if isinstance(decaying_model, MISPDecayingModel): decaying_model_id = decaying_model.id @@ -2511,7 +2511,7 @@ class PyMISP: response = self._prepare_request('POST', f'decayingModel/enable/{decaying_model_id}') return self._check_json_response(response) - def disable_decaying_model(self, decaying_model: MISPDecayingModel | int | str) -> dict[str, Any]: + def disable_decaying_model(self, decaying_model: MISPDecayingModel | int | str) -> dict[str, Any] | list[dict[str, Any]]: """Disable a decaying Model""" if isinstance(decaying_model, MISPDecayingModel): decaying_model_id = decaying_model.id @@ -2740,7 +2740,7 @@ class PyMISP: normalized_response: list[dict[str, Any]] | dict[str, Any] if controller in ['events', 'objects']: # This one is truly fucked: event returns a list, attributes doesn't. - normalized_response = self._check_json_response_list(response) + normalized_response = self._check_json_response(response) elif controller == 'attributes': normalized_response = self._check_json_response(response) @@ -2882,7 +2882,7 @@ class PyMISP: query["direction"] = "desc" if desc else "asc" url = urljoin(self.root_url, 'events/index') response = self._prepare_request('POST', url, data=query) - normalized_response = self._check_json_response_list(response) + normalized_response = self._check_json_response(response) if not (self.global_pythonify or pythonify) or isinstance(normalized_response, dict): return normalized_response @@ -2958,7 +2958,7 @@ class PyMISP: url = urljoin(self.root_url, url_path) response = self._prepare_request('POST', url, data=query) - normalized_response = self._check_json_response_list(response) + normalized_response = self._check_json_response(response) if not (self.global_pythonify or pythonify) or isinstance(normalized_response, dict): return normalized_response @@ -3019,7 +3019,7 @@ class PyMISP: query['created'] = query.pop('created').timestamp() response = self._prepare_request('POST', 'admin/logs/index', data=query) - normalized_response = self._check_json_response_list(response) + normalized_response = self._check_json_response(response) if not (self.global_pythonify or pythonify) or isinstance(normalized_response, dict): return normalized_response @@ -3033,7 +3033,7 @@ class PyMISP: def search_feeds(self, value: SearchParameterTypes | None = None, pythonify: bool | None = False) -> dict[str, Any] | list[MISPFeed] | list[dict[str, Any]]: '''Search in the feeds cached on the servers''' response = self._prepare_request('POST', 'feeds/searchCaches', data={'value': value}) - normalized_response = self._check_json_response_list(response) + normalized_response = self._check_json_response(response) if not (self.global_pythonify or pythonify) or isinstance(normalized_response, dict): return normalized_response to_return = [] @@ -3053,7 +3053,7 @@ class PyMISP: :param pythonify: Returns a list of PyMISP Objects instead of the plain json output. Warning: it might use a lot of RAM """ r = self._prepare_request('GET', 'communities/index') - communities = self._check_json_response_list(r) + communities = self._check_json_response(r) if not (self.global_pythonify or pythonify) or isinstance(communities, dict): return communities to_return = [] @@ -3086,7 +3086,7 @@ class PyMISP: requestor_organisation_description: str | None = None, message: str | None = None, sync: bool = False, anonymise_requestor_server: bool = False, - mock: bool = False) -> dict[str, Any]: + mock: bool = False) -> dict[str, Any] | list[dict[str, Any]]: """Request the access to a community :param community: community to request access @@ -3120,7 +3120,7 @@ class PyMISP: :param pythonify: Returns a list of PyMISP Objects instead of the plain json output. Warning: it might use a lot of RAM """ r = self._prepare_request('GET', 'eventDelegations') - delegations = self._check_json_response_list(r) + delegations = self._check_json_response(r) if not (self.global_pythonify or pythonify) or isinstance(delegations, dict): return delegations to_return = [] @@ -3130,7 +3130,7 @@ class PyMISP: to_return.append(d) return to_return - def accept_event_delegation(self, delegation: MISPEventDelegation | int | str, pythonify: bool = False) -> dict[str, Any]: + def accept_event_delegation(self, delegation: MISPEventDelegation | int | str, pythonify: bool = False) -> dict[str, Any] | list[dict[str, Any]]: """Accept the delegation of an event :param delegation: event delegation to accept @@ -3140,7 +3140,7 @@ class PyMISP: r = self._prepare_request('POST', f'eventDelegations/acceptDelegation/{delegation_id}') return self._check_json_response(r) - def discard_event_delegation(self, delegation: MISPEventDelegation | int | str, pythonify: bool = False) -> dict[str, Any]: + def discard_event_delegation(self, delegation: MISPEventDelegation | int | str, pythonify: bool = False) -> dict[str, Any] | list[dict[str, Any]]: """Discard the delegation of an event :param delegation: event delegation to discard @@ -3183,7 +3183,7 @@ class PyMISP: # ## BEGIN Others ### - def push_event_to_ZMQ(self, event: MISPEvent | int | str | UUID) -> dict[str, Any]: + def push_event_to_ZMQ(self, event: MISPEvent | int | str | UUID) -> dict[str, Any] | list[dict[str, Any]]: """Force push an event by id on ZMQ :param event: the event to push @@ -3231,7 +3231,7 @@ class PyMISP: if returnMetaAttributes: query['returnMetaAttributes'] = returnMetaAttributes r = self._prepare_request('POST', f'events/freeTextImport/{event_id}', data=query, **kwargs) - attributes = self._check_json_response_list(r) + attributes = self._check_json_response(r) if returnMetaAttributes or not (self.global_pythonify or pythonify) or isinstance(attributes, dict): return attributes to_return = [] @@ -3273,7 +3273,7 @@ class PyMISP: # ## BEGIN Statistics ### - def attributes_statistics(self, context: str = 'type', percentage: bool = False) -> dict[str, Any]: + def attributes_statistics(self, context: str = 'type', percentage: bool = False) -> dict[str, Any] | list[dict[str, Any]]: """Get attribute statistics from the MISP instance :param context: "type" or "category" @@ -3289,7 +3289,7 @@ class PyMISP: response = self._prepare_request('GET', path) return self._check_json_response(response) - def tags_statistics(self, percentage: bool = False, name_sort: bool = False) -> dict[str, Any]: + def tags_statistics(self, percentage: bool = False, name_sort: bool = False) -> dict[str, Any] | list[dict[str, Any]]: """Get tag statistics from the MISP instance :param percentage: get percentages @@ -3318,7 +3318,7 @@ class PyMISP: raise PyMISPError("context can only be {','.join(availables_contexts)}") response = self._prepare_request('GET', f'users/statistics/{context}') try: - return self._check_json_response_list(response) + return self._check_json_response(response) except PyMISPError: return self._check_json_response(response) @@ -3332,7 +3332,7 @@ class PyMISP: :param pythonify: Returns a list of PyMISP Objects instead of the plain json output. Warning: it might use a lot of RAM """ r = self._prepare_request('GET', 'userSettings/index') - user_settings = self._check_json_response_list(r) + user_settings = self._check_json_response(r) if not (self.global_pythonify or pythonify) or isinstance(user_settings, dict): return user_settings to_return = [] @@ -3384,7 +3384,7 @@ class PyMISP: u.from_dict(**user_setting_j) return u - def delete_user_setting(self, user_setting: str, user: MISPUser | int | str | UUID | None = None) -> dict[str, Any]: + def delete_user_setting(self, user_setting: str, user: MISPUser | int | str | UUID | None = None) -> dict[str, Any] | list[dict[str, Any]]: """Delete a user setting: https://www.misp-project.org/openapi/#tag/UserSettings/operation/deleteUserSettingById :param user_setting: name of user setting @@ -3406,7 +3406,7 @@ class PyMISP: :param pythonify: Returns a list of PyMISP Objects instead of the plain json output. Warning: it might use a lot of RAM """ r = self._prepare_request('GET', 'eventBlocklists/index') - event_blocklists = self._check_json_response_list(r) + event_blocklists = self._check_json_response(r) if not (self.global_pythonify or pythonify) or isinstance(event_blocklists, dict): return event_blocklists to_return = [] @@ -3422,7 +3422,7 @@ class PyMISP: :param pythonify: Returns a list of PyMISP Objects instead of the plain json output. Warning: it might use a lot of RAM """ r = self._prepare_request('GET', 'orgBlocklists/index') - organisation_blocklists = self._check_json_response_list(r) + organisation_blocklists = self._check_json_response(r) if not (self.global_pythonify or pythonify) or isinstance(organisation_blocklists, dict): return organisation_blocklists to_return = [] @@ -3432,7 +3432,7 @@ class PyMISP: to_return.append(obl) return to_return - def _add_entries_to_blocklist(self, blocklist_type: str, uuids: str | list[str], **kwargs) -> dict[str, Any]: # type: ignore[no-untyped-def] + def _add_entries_to_blocklist(self, blocklist_type: str, uuids: str | list[str], **kwargs) -> dict[str, Any] | list[dict[str, Any]]: # type: ignore[no-untyped-def] if blocklist_type == 'event': url = 'eventBlocklists/add' elif blocklist_type == 'organisation': @@ -3448,7 +3448,7 @@ class PyMISP: return self._check_json_response(r) def add_event_blocklist(self, uuids: str | list[str], comment: str | None = None, - event_info: str | None = None, event_orgc: str | None = None) -> dict[str, Any]: + event_info: str | None = None, event_orgc: str | None = None) -> dict[str, Any] | list[dict[str, Any]]: """Add a new event in the blocklist :param uuids: UUIDs @@ -3459,7 +3459,7 @@ class PyMISP: return self._add_entries_to_blocklist('event', uuids=uuids, comment=comment, event_info=event_info, event_orgc=event_orgc) def add_organisation_blocklist(self, uuids: str | list[str], comment: str | None = None, - org_name: str | None = None) -> dict[str, Any]: + org_name: str | None = None) -> dict[str, Any] | list[dict[str, Any]]: """Add a new organisation in the blocklist :param uuids: UUIDs @@ -3468,7 +3468,7 @@ class PyMISP: """ return self._add_entries_to_blocklist('organisation', uuids=uuids, comment=comment, org_name=org_name) - def _update_entries_in_blocklist(self, blocklist_type: str, uuid, **kwargs) -> dict[str, Any]: # type: ignore[no-untyped-def] + def _update_entries_in_blocklist(self, blocklist_type: str, uuid, **kwargs) -> dict[str, Any] | list[dict[str, Any]]: # type: ignore[no-untyped-def] if blocklist_type == 'event': url = f'eventBlocklists/edit/{uuid}' elif blocklist_type == 'organisation': @@ -3515,7 +3515,7 @@ class PyMISP: o.from_dict(**updated_organisation_blocklist) return o - def delete_event_blocklist(self, event_blocklist: MISPEventBlocklist | str | UUID) -> dict[str, Any]: + def delete_event_blocklist(self, event_blocklist: MISPEventBlocklist | str | UUID) -> dict[str, Any] | list[dict[str, Any]]: """Delete a blocklisted event by id :param event_blocklist: event block list to delete @@ -3524,7 +3524,7 @@ class PyMISP: response = self._prepare_request('POST', f'eventBlocklists/delete/{event_blocklist_id}') return self._check_json_response(response) - def delete_organisation_blocklist(self, organisation_blocklist: MISPOrganisationBlocklist | str | UUID) -> dict[str, Any]: + def delete_organisation_blocklist(self, organisation_blocklist: MISPOrganisationBlocklist | str | UUID) -> dict[str, Any] | list[dict[str, Any]]: """Delete a blocklisted organisation by id :param organisation_blocklist: organization block list to delete @@ -3561,7 +3561,7 @@ class PyMISP: raise PyMISPError('The misp_entity must be MISPEvent, MISPObject or MISPAttribute') def tag(self, misp_entity: AbstractMISP | str | dict[str, Any], tag: MISPTag | str, - local: bool = False, relationship_type: str | None = None) -> dict[str, Any]: + local: bool = False, relationship_type: str | None = None) -> dict[str, Any] | list[dict[str, Any]]: """Tag an event or an attribute. :param misp_entity: a MISPEvent, a MISP Attribute, or a UUID @@ -3580,7 +3580,7 @@ class PyMISP: response = self._prepare_request('POST', 'tags/attachTagToObject', data=to_post) return self._check_json_response(response) - def untag(self, misp_entity: AbstractMISP | str | dict[str, Any], tag: MISPTag | str) -> dict[str, Any]: + def untag(self, misp_entity: AbstractMISP | str | dict[str, Any], tag: MISPTag | str) -> dict[str, Any] | list[dict[str, Any]]: """Untag an event or an attribute :param misp_entity: misp_entity can be a UUID @@ -3690,18 +3690,9 @@ class PyMISP: return value return value - def _check_json_response_list(self, response: requests.Response) -> dict[str, Any] | list[dict[str, Any]]: + def _check_json_response(self, response: requests.Response) -> dict[str, Any] | list[dict[str, Any]]: r = self._check_response(response, expect_json=True) - if isinstance(r, dict) and 'errors' in r: - return r - if isinstance(r, list): - return r - # Else: an exception was raised anyway - raise PyMISPUnexpectedResponse(f'A list was expected, got a {type(r)}: {r}') - - def _check_json_response(self, response: requests.Response) -> dict[str, Any]: - r = self._check_response(response, expect_json=True) - if isinstance(r, dict): + if isinstance(r, (dict, list)): return r # Else: an exception was raised anyway raise PyMISPUnexpectedResponse(f'A dict was expected, got a string: {r}') From 5e76e366679cfce6c4b0419ebe70581c14b08ad9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Vinot?= Date: Fri, 2 Feb 2024 15:24:07 +0100 Subject: [PATCH 66/80] chg: Bump deps, version, objects --- poetry.lock | 12 ++++++------ pymisp/data/misp-objects | 2 +- pyproject.toml | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/poetry.lock b/poetry.lock index 5a64b9b..0a78f64 100644 --- a/poetry.lock +++ b/poetry.lock @@ -410,13 +410,13 @@ cffi = ">=1.0.0" [[package]] name = "certifi" -version = "2023.11.17" +version = "2024.2.2" description = "Python package for providing Mozilla's CA Bundle." optional = false python-versions = ">=3.6" files = [ - {file = "certifi-2023.11.17-py3-none-any.whl", hash = "sha256:e036ab49d5b79556f99cfc2d9320b34cfbe5be05c5871b51de9329f0603b0474"}, - {file = "certifi-2023.11.17.tar.gz", hash = "sha256:9b469f3a900bf28dc19b8cfbf8019bf47f7fdd1a65a1d4ffb98fc14166beb4d1"}, + {file = "certifi-2024.2.2-py3-none-any.whl", hash = "sha256:dc383c07b76109f368f6106eee2b593b04a011ea4d55f652c6ca24a754d1cdd1"}, + {file = "certifi-2024.2.2.tar.gz", hash = "sha256:0569859f95fc761b18b45ef421b1290a0f65f147e92a1e5eb3e635f9a5e4e66f"}, ] [[package]] @@ -2311,13 +2311,13 @@ files = [ [[package]] name = "pytz" -version = "2023.4" +version = "2024.1" description = "World timezone definitions, modern and historical" optional = false python-versions = "*" files = [ - {file = "pytz-2023.4-py2.py3-none-any.whl", hash = "sha256:f90ef520d95e7c46951105338d918664ebfd6f1d995bd7d153127ce90efafa6a"}, - {file = "pytz-2023.4.tar.gz", hash = "sha256:31d4583c4ed539cd037956140d695e42c033a19e984bfce9964a3f7d59bc2b40"}, + {file = "pytz-2024.1-py2.py3-none-any.whl", hash = "sha256:328171f4e3623139da4983451950b28e95ac706e13f3f2630a879749e7a8b319"}, + {file = "pytz-2024.1.tar.gz", hash = "sha256:2a29735ea9c18baf14b448846bde5a48030ed267578472d8955cd0e7443a9812"}, ] [[package]] diff --git a/pymisp/data/misp-objects b/pymisp/data/misp-objects index 888e0dc..3ac5099 160000 --- a/pymisp/data/misp-objects +++ b/pymisp/data/misp-objects @@ -1 +1 @@ -Subproject commit 888e0dceda905076635ecc7d589ee3effe3c45d6 +Subproject commit 3ac509965fdbca06d8a027db22c0064588babd3c diff --git a/pyproject.toml b/pyproject.toml index f5b9876..803782f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "pymisp" -version = "2.4.183" +version = "2.4.184" description = "Python API for MISP." authors = ["Raphaël Vinot "] license = "BSD-2-Clause" From c0077c19cf3843a65d5b26076dd26deca0405033 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Vinot?= Date: Fri, 2 Feb 2024 15:28:07 +0100 Subject: [PATCH 67/80] chg: Bump changelog --- CHANGELOG.txt | 77 +++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 75 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index f12dcc5..638163e 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -2,6 +2,80 @@ Changelog ========= +v2.4.184 (2024-02-02) +--------------------- + +New +~~~ +- Enable support for python 3.12. [Raphaël Vinot] +- Relationship_type in tag. [Raphaël Vinot] + + Fix https://github.com/MISP/MISP/issues/9483 +- [internal] Add support for orjson. [Jakub Onderka] + + orjson is much faster library for decoding and encoding JSON formats + +Changes +~~~~~~~ +- Bump deps, version, objects. [Raphaël Vinot] +- Remove IntEnum. [Raphaël Vinot] +- Add even more debug for gha. [Raphaël Vinot] +- Add some debug for gha. [Raphaël Vinot] +- Bump deps. [Raphaël Vinot] +- Add more strict typing, not done yet. [Raphaël Vinot] +- Add a bunch more typing. [Raphaël Vinot] +- Use typing info of lief. [Raphaël Vinot] +- First batch of changes for strict typing. [Raphaël Vinot] +- Update typing to please lief. [Raphaël Vinot] +- Bump deps. [Raphaël Vinot] +- [internal] Simplify code. [Jakub Onderka] +- [internal] User faster method to convert bytes to str. [Jakub Onderka] +- New annotations in tests. [Raphaël Vinot] +- Initial changes to use new annotations. [Raphaël Vinot] +- Bump deps. [Raphaël Vinot] +- Bump deps, try to install with python 3.12. [Raphaël Vinot] +- Make the publish_timestamp a string, as per specs. [Raphaël Vinot] +- [internal] Update poetry.lock. [Jakub Onderka] + +Fix +~~~ +- Revert typing changes. [Raphaël Vinot] +- More responses athat are lists. [Raphaël Vinot] +- Another call that cn be a list or a dict. [Raphaël Vinot] +- Do not cast enum. [Raphaël Vinot] +- More fixes to support responses from MISP. [Raphaël Vinot] +- Handle list responses properly. [Raphaël Vinot] +- Import FileObject as needed. [Raphaël Vinot] +- Also skip docs from mypy. [Raphaël Vinot] +- Run mypy on what I want. [Raphaël Vinot] +- Compatibility with python 3.8. [Raphaël Vinot] +- Python < 3.10 support on typing, for good. [Raphaël Vinot] +- Python < 3.10 support on typing. [Raphaël Vinot] +- Rollback tests on python 3.12 as lief is not supported yet. [Raphaël + Vinot] +- Add missing wheel. [Raphaël Vinot] +- Make publish_timestamp a string in tests. [Raphaël Vinot] +- [internal] README typos. [Jakub Onderka] + +Other +~~~~~ +- Revert "fix: More responses athat are lists" [Raphaël Vinot] + + This reverts commit 709a10c64c0513b515f25c3ecfb9eb577b55084b. +- Build(deps): bump jinja2 from 3.1.2 to 3.1.3. [dependabot[bot]] + + Bumps [jinja2](https://github.com/pallets/jinja) from 3.1.2 to 3.1.3. + - [Release notes](https://github.com/pallets/jinja/releases) + - [Changelog](https://github.com/pallets/jinja/blob/main/CHANGES.rst) + - [Commits](https://github.com/pallets/jinja/compare/3.1.2...3.1.3) + + --- + updated-dependencies: + - dependency-name: jinja2 + dependency-type: indirect + ... + + v2.4.183 (2024-01-04) --------------------- @@ -11,6 +85,7 @@ New Changes ~~~~~~~ +- Bump changelog. [Raphaël Vinot] - Bump objects. [Raphaël Vinot] - Bump version. [Raphaël Vinot] - Remove jsonschema from dependencies. [Raphaël Vinot] @@ -5170,5 +5245,3 @@ v1.1.2 (2015-08-05) - Json export is not supported everywhere. [Raphaël Vinot] - Some testing. [Raphaël Vinot] - Initial commit. [Raphaël Vinot] - - From 1b1133c09c5da6cfe29ad91beef3d3c53e8d6d49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Vinot?= Date: Tue, 6 Feb 2024 14:46:59 +0100 Subject: [PATCH 68/80] chg: re-add ExpandedPyMISP, with a warning --- poetry.lock | 221 ++++++++++++++++++++++++++++----------------- pymisp/__init__.py | 8 +- pyproject.toml | 4 +- 3 files changed, 147 insertions(+), 86 deletions(-) diff --git a/poetry.lock b/poetry.lock index 0a78f64..8b7281b 100644 --- a/poetry.lock +++ b/poetry.lock @@ -46,13 +46,13 @@ trio = ["trio (>=0.23)"] [[package]] name = "appnope" -version = "0.1.3" +version = "0.1.4" description = "Disable App Nap on macOS >= 10.9" optional = false -python-versions = "*" +python-versions = ">=3.6" files = [ - {file = "appnope-0.1.3-py2.py3-none-any.whl", hash = "sha256:265a455292d0bd8a72453494fa24df5a11eb18373a60c7c0430889f22548605e"}, - {file = "appnope-0.1.3.tar.gz", hash = "sha256:02bd91c4de869fbb1e1c50aafc4098827a7a54ab2f39d9dcba6c9547ed920e24"}, + {file = "appnope-0.1.4-py2.py3-none-any.whl", hash = "sha256:502575ee11cd7a28c0205f379b525beefebab9d161b7c964670864014ed7213c"}, + {file = "appnope-0.1.4.tar.gz", hash = "sha256:1de3860566df9caf38f01f86f65e0e13e379af54f9e4bee1e66b48f2efffd1ee"}, ] [[package]] @@ -939,6 +939,62 @@ files = [ {file = "fqdn-1.5.1.tar.gz", hash = "sha256:105ed3677e767fb5ca086a0c1f4bb66ebc3c100be518f0e0d755d9eae164d89f"}, ] +[[package]] +name = "h11" +version = "0.14.0" +description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" +optional = false +python-versions = ">=3.7" +files = [ + {file = "h11-0.14.0-py3-none-any.whl", hash = "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761"}, + {file = "h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d"}, +] + +[[package]] +name = "httpcore" +version = "1.0.2" +description = "A minimal low-level HTTP client." +optional = false +python-versions = ">=3.8" +files = [ + {file = "httpcore-1.0.2-py3-none-any.whl", hash = "sha256:096cc05bca73b8e459a1fc3dcf585148f63e534eae4339559c9b8a8d6399acc7"}, + {file = "httpcore-1.0.2.tar.gz", hash = "sha256:9fc092e4799b26174648e54b74ed5f683132a464e95643b226e00c2ed2fa6535"}, +] + +[package.dependencies] +certifi = "*" +h11 = ">=0.13,<0.15" + +[package.extras] +asyncio = ["anyio (>=4.0,<5.0)"] +http2 = ["h2 (>=3,<5)"] +socks = ["socksio (==1.*)"] +trio = ["trio (>=0.22.0,<0.23.0)"] + +[[package]] +name = "httpx" +version = "0.26.0" +description = "The next generation HTTP client." +optional = false +python-versions = ">=3.8" +files = [ + {file = "httpx-0.26.0-py3-none-any.whl", hash = "sha256:8915f5a3627c4d47b73e8202457cb28f1266982d1159bd5779d86a80c0eab1cd"}, + {file = "httpx-0.26.0.tar.gz", hash = "sha256:451b55c30d5185ea6b23c2c793abf9bb237d2a7dfb901ced6ff69ad37ec1dfaf"}, +] + +[package.dependencies] +anyio = "*" +certifi = "*" +httpcore = "==1.*" +idna = "*" +sniffio = "*" + +[package.extras] +brotli = ["brotli", "brotlicffi"] +cli = ["click (==8.*)", "pygments (==2.*)", "rich (>=10,<14)"] +http2 = ["h2 (>=3,<5)"] +socks = ["socksio (==1.*)"] + [[package]] name = "idna" version = "3.6" @@ -1011,13 +1067,13 @@ files = [ [[package]] name = "ipykernel" -version = "6.29.0" +version = "6.29.1" description = "IPython Kernel for Jupyter" optional = false python-versions = ">=3.8" files = [ - {file = "ipykernel-6.29.0-py3-none-any.whl", hash = "sha256:076663ca68492576f051e4af7720d33f34383e655f2be0d544c8b1c9de915b2f"}, - {file = "ipykernel-6.29.0.tar.gz", hash = "sha256:b5dd3013cab7b330df712891c96cd1ab868c27a7159e606f762015e9bf8ceb3f"}, + {file = "ipykernel-6.29.1-py3-none-any.whl", hash = "sha256:e5dfba210fc9da74a5dae8fa6c41f816e11bd18d10381b2517d9a0d57cc987c4"}, + {file = "ipykernel-6.29.1.tar.gz", hash = "sha256:1547352b32da95a2761011a8dac2af930c26a0703dfa07690d16b7d74dac0ba1"}, ] [package.dependencies] @@ -1040,7 +1096,7 @@ cov = ["coverage[toml]", "curio", "matplotlib", "pytest-cov", "trio"] docs = ["myst-parser", "pydata-sphinx-theme", "sphinx", "sphinx-autodoc-typehints", "sphinxcontrib-github-alt", "sphinxcontrib-spelling", "trio"] pyqt5 = ["pyqt5"] pyside6 = ["pyside6"] -test = ["flaky", "ipyparallel", "pre-commit", "pytest (>=7.0)", "pytest-asyncio (==0.23.2)", "pytest-cov", "pytest-timeout"] +test = ["flaky", "ipyparallel", "pre-commit", "pytest (>=7.0)", "pytest-asyncio (==0.23.4)", "pytest-cov", "pytest-timeout"] [[package]] name = "ipython" @@ -1415,17 +1471,18 @@ test = ["jupyter-server (>=2.0.0)", "pytest (>=7.0)", "pytest-jupyter[server] (> [[package]] name = "jupyterlab" -version = "4.0.12" +version = "4.1.0" description = "JupyterLab computational environment" optional = false python-versions = ">=3.8" files = [ - {file = "jupyterlab-4.0.12-py3-none-any.whl", hash = "sha256:53f132480e5f6564f4e20d1b5ed4e8b7945952a2decd5bdfa43760b1b536c99d"}, - {file = "jupyterlab-4.0.12.tar.gz", hash = "sha256:965d92efa82a538ed70ccb3968d9aabba788840da882e13d7b061780cdedc3b7"}, + {file = "jupyterlab-4.1.0-py3-none-any.whl", hash = "sha256:5380e85fb4f11a227ed2db13103e513cfea274d1011f6210e62d611e92e0369d"}, + {file = "jupyterlab-4.1.0.tar.gz", hash = "sha256:92cdfd86c53e163fb9e91e14497901153536c5a889c9225dade270f6107a077f"}, ] [package.dependencies] async-lru = ">=1.0.0" +httpx = ">=0.25.0" importlib-metadata = {version = ">=4.8.3", markers = "python_version < \"3.10\""} importlib-resources = {version = ">=1.4", markers = "python_version < \"3.9\""} ipykernel = "*" @@ -1441,9 +1498,9 @@ tornado = ">=6.2.0" traitlets = "*" [package.extras] -dev = ["build", "bump2version", "coverage", "hatch", "pre-commit", "pytest-cov", "ruff (==0.1.6)"] -docs = ["jsx-lexer", "myst-parser", "pydata-sphinx-theme (>=0.13.0)", "pytest", "pytest-check-links", "pytest-tornasync", "sphinx (>=1.8,<7.2.0)", "sphinx-copybutton"] -docs-screenshots = ["altair (==5.0.1)", "ipython (==8.14.0)", "ipywidgets (==8.0.6)", "jupyterlab-geojson (==3.4.0)", "jupyterlab-language-pack-zh-cn (==4.0.post0)", "matplotlib (==3.7.1)", "nbconvert (>=7.0.0)", "pandas (==2.0.2)", "scipy (==1.10.1)", "vega-datasets (==0.9.0)"] +dev = ["build", "bump2version", "coverage", "hatch", "pre-commit", "pytest-cov", "ruff (==0.1.15)"] +docs = ["jsx-lexer", "myst-parser", "pydata-sphinx-theme (>=0.13.0)", "pytest", "pytest-check-links", "pytest-jupyter", "sphinx (>=1.8,<7.3.0)", "sphinx-copybutton"] +docs-screenshots = ["altair (==5.2.0)", "ipython (==8.16.1)", "ipywidgets (==8.1.1)", "jupyterlab-geojson (==3.4.0)", "jupyterlab-language-pack-zh-cn (==4.0.post6)", "matplotlib (==3.8.2)", "nbconvert (>=7.0.0)", "pandas (==2.2.0)", "scipy (==1.12.0)", "vega-datasets (==0.9.0)"] test = ["coverage", "pytest (>=7.0)", "pytest-check-links (>=0.7)", "pytest-console-scripts", "pytest-cov", "pytest-jupyter (>=0.5.3)", "pytest-timeout", "pytest-tornasync", "requests", "requests-cache", "virtualenv"] [[package]] @@ -1541,71 +1598,71 @@ files = [ [[package]] name = "markupsafe" -version = "2.1.4" +version = "2.1.5" description = "Safely add untrusted strings to HTML/XML markup." optional = false python-versions = ">=3.7" files = [ - {file = "MarkupSafe-2.1.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:de8153a7aae3835484ac168a9a9bdaa0c5eee4e0bc595503c95d53b942879c84"}, - {file = "MarkupSafe-2.1.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e888ff76ceb39601c59e219f281466c6d7e66bd375b4ec1ce83bcdc68306796b"}, - {file = "MarkupSafe-2.1.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0b838c37ba596fcbfca71651a104a611543077156cb0a26fe0c475e1f152ee8"}, - {file = "MarkupSafe-2.1.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dac1ebf6983148b45b5fa48593950f90ed6d1d26300604f321c74a9ca1609f8e"}, - {file = "MarkupSafe-2.1.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0fbad3d346df8f9d72622ac71b69565e621ada2ce6572f37c2eae8dacd60385d"}, - {file = "MarkupSafe-2.1.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:d5291d98cd3ad9a562883468c690a2a238c4a6388ab3bd155b0c75dd55ece858"}, - {file = "MarkupSafe-2.1.4-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:a7cc49ef48a3c7a0005a949f3c04f8baa5409d3f663a1b36f0eba9bfe2a0396e"}, - {file = "MarkupSafe-2.1.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:b83041cda633871572f0d3c41dddd5582ad7d22f65a72eacd8d3d6d00291df26"}, - {file = "MarkupSafe-2.1.4-cp310-cp310-win32.whl", hash = "sha256:0c26f67b3fe27302d3a412b85ef696792c4a2386293c53ba683a89562f9399b0"}, - {file = "MarkupSafe-2.1.4-cp310-cp310-win_amd64.whl", hash = "sha256:a76055d5cb1c23485d7ddae533229039b850db711c554a12ea64a0fd8a0129e2"}, - {file = "MarkupSafe-2.1.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9e9e3c4020aa2dc62d5dd6743a69e399ce3de58320522948af6140ac959ab863"}, - {file = "MarkupSafe-2.1.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:0042d6a9880b38e1dd9ff83146cc3c9c18a059b9360ceae207805567aacccc69"}, - {file = "MarkupSafe-2.1.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:55d03fea4c4e9fd0ad75dc2e7e2b6757b80c152c032ea1d1de487461d8140efc"}, - {file = "MarkupSafe-2.1.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ab3a886a237f6e9c9f4f7d272067e712cdb4efa774bef494dccad08f39d8ae6"}, - {file = "MarkupSafe-2.1.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:abf5ebbec056817057bfafc0445916bb688a255a5146f900445d081db08cbabb"}, - {file = "MarkupSafe-2.1.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e1a0d1924a5013d4f294087e00024ad25668234569289650929ab871231668e7"}, - {file = "MarkupSafe-2.1.4-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:e7902211afd0af05fbadcc9a312e4cf10f27b779cf1323e78d52377ae4b72bea"}, - {file = "MarkupSafe-2.1.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:c669391319973e49a7c6230c218a1e3044710bc1ce4c8e6eb71f7e6d43a2c131"}, - {file = "MarkupSafe-2.1.4-cp311-cp311-win32.whl", hash = "sha256:31f57d64c336b8ccb1966d156932f3daa4fee74176b0fdc48ef580be774aae74"}, - {file = "MarkupSafe-2.1.4-cp311-cp311-win_amd64.whl", hash = "sha256:54a7e1380dfece8847c71bf7e33da5d084e9b889c75eca19100ef98027bd9f56"}, - {file = "MarkupSafe-2.1.4-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:a76cd37d229fc385738bd1ce4cba2a121cf26b53864c1772694ad0ad348e509e"}, - {file = "MarkupSafe-2.1.4-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:987d13fe1d23e12a66ca2073b8d2e2a75cec2ecb8eab43ff5624ba0ad42764bc"}, - {file = "MarkupSafe-2.1.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5244324676254697fe5c181fc762284e2c5fceeb1c4e3e7f6aca2b6f107e60dc"}, - {file = "MarkupSafe-2.1.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:78bc995e004681246e85e28e068111a4c3f35f34e6c62da1471e844ee1446250"}, - {file = "MarkupSafe-2.1.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a4d176cfdfde84f732c4a53109b293d05883e952bbba68b857ae446fa3119b4f"}, - {file = "MarkupSafe-2.1.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:f9917691f410a2e0897d1ef99619fd3f7dd503647c8ff2475bf90c3cf222ad74"}, - {file = "MarkupSafe-2.1.4-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:f06e5a9e99b7df44640767842f414ed5d7bedaaa78cd817ce04bbd6fd86e2dd6"}, - {file = "MarkupSafe-2.1.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:396549cea79e8ca4ba65525470d534e8a41070e6b3500ce2414921099cb73e8d"}, - {file = "MarkupSafe-2.1.4-cp312-cp312-win32.whl", hash = "sha256:f6be2d708a9d0e9b0054856f07ac7070fbe1754be40ca8525d5adccdbda8f475"}, - {file = "MarkupSafe-2.1.4-cp312-cp312-win_amd64.whl", hash = "sha256:5045e892cfdaecc5b4c01822f353cf2c8feb88a6ec1c0adef2a2e705eef0f656"}, - {file = "MarkupSafe-2.1.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:7a07f40ef8f0fbc5ef1000d0c78771f4d5ca03b4953fc162749772916b298fc4"}, - {file = "MarkupSafe-2.1.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d18b66fe626ac412d96c2ab536306c736c66cf2a31c243a45025156cc190dc8a"}, - {file = "MarkupSafe-2.1.4-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:698e84142f3f884114ea8cf83e7a67ca8f4ace8454e78fe960646c6c91c63bfa"}, - {file = "MarkupSafe-2.1.4-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:49a3b78a5af63ec10d8604180380c13dcd870aba7928c1fe04e881d5c792dc4e"}, - {file = "MarkupSafe-2.1.4-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:15866d7f2dc60cfdde12ebb4e75e41be862348b4728300c36cdf405e258415ec"}, - {file = "MarkupSafe-2.1.4-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:6aa5e2e7fc9bc042ae82d8b79d795b9a62bd8f15ba1e7594e3db243f158b5565"}, - {file = "MarkupSafe-2.1.4-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:54635102ba3cf5da26eb6f96c4b8c53af8a9c0d97b64bdcb592596a6255d8518"}, - {file = "MarkupSafe-2.1.4-cp37-cp37m-win32.whl", hash = "sha256:3583a3a3ab7958e354dc1d25be74aee6228938312ee875a22330c4dc2e41beb0"}, - {file = "MarkupSafe-2.1.4-cp37-cp37m-win_amd64.whl", hash = "sha256:d6e427c7378c7f1b2bef6a344c925b8b63623d3321c09a237b7cc0e77dd98ceb"}, - {file = "MarkupSafe-2.1.4-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:bf1196dcc239e608605b716e7b166eb5faf4bc192f8a44b81e85251e62584bd2"}, - {file = "MarkupSafe-2.1.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:4df98d4a9cd6a88d6a585852f56f2155c9cdb6aec78361a19f938810aa020954"}, - {file = "MarkupSafe-2.1.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b835aba863195269ea358cecc21b400276747cc977492319fd7682b8cd2c253d"}, - {file = "MarkupSafe-2.1.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:23984d1bdae01bee794267424af55eef4dfc038dc5d1272860669b2aa025c9e3"}, - {file = "MarkupSafe-2.1.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1c98c33ffe20e9a489145d97070a435ea0679fddaabcafe19982fe9c971987d5"}, - {file = "MarkupSafe-2.1.4-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:9896fca4a8eb246defc8b2a7ac77ef7553b638e04fbf170bff78a40fa8a91474"}, - {file = "MarkupSafe-2.1.4-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:b0fe73bac2fed83839dbdbe6da84ae2a31c11cfc1c777a40dbd8ac8a6ed1560f"}, - {file = "MarkupSafe-2.1.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:c7556bafeaa0a50e2fe7dc86e0382dea349ebcad8f010d5a7dc6ba568eaaa789"}, - {file = "MarkupSafe-2.1.4-cp38-cp38-win32.whl", hash = "sha256:fc1a75aa8f11b87910ffd98de62b29d6520b6d6e8a3de69a70ca34dea85d2a8a"}, - {file = "MarkupSafe-2.1.4-cp38-cp38-win_amd64.whl", hash = "sha256:3a66c36a3864df95e4f62f9167c734b3b1192cb0851b43d7cc08040c074c6279"}, - {file = "MarkupSafe-2.1.4-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:765f036a3d00395a326df2835d8f86b637dbaf9832f90f5d196c3b8a7a5080cb"}, - {file = "MarkupSafe-2.1.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:21e7af8091007bf4bebf4521184f4880a6acab8df0df52ef9e513d8e5db23411"}, - {file = "MarkupSafe-2.1.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d5c31fe855c77cad679b302aabc42d724ed87c043b1432d457f4976add1c2c3e"}, - {file = "MarkupSafe-2.1.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7653fa39578957bc42e5ebc15cf4361d9e0ee4b702d7d5ec96cdac860953c5b4"}, - {file = "MarkupSafe-2.1.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:47bb5f0142b8b64ed1399b6b60f700a580335c8e1c57f2f15587bd072012decc"}, - {file = "MarkupSafe-2.1.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:fe8512ed897d5daf089e5bd010c3dc03bb1bdae00b35588c49b98268d4a01e00"}, - {file = "MarkupSafe-2.1.4-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:36d7626a8cca4d34216875aee5a1d3d654bb3dac201c1c003d182283e3205949"}, - {file = "MarkupSafe-2.1.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:b6f14a9cd50c3cb100eb94b3273131c80d102e19bb20253ac7bd7336118a673a"}, - {file = "MarkupSafe-2.1.4-cp39-cp39-win32.whl", hash = "sha256:c8f253a84dbd2c63c19590fa86a032ef3d8cc18923b8049d91bcdeeb2581fbf6"}, - {file = "MarkupSafe-2.1.4-cp39-cp39-win_amd64.whl", hash = "sha256:8b570a1537367b52396e53325769608f2a687ec9a4363647af1cded8928af959"}, - {file = "MarkupSafe-2.1.4.tar.gz", hash = "sha256:3aae9af4cac263007fd6309c64c6ab4506dd2b79382d9d19a1994f9240b8db4f"}, + {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]] @@ -1730,13 +1787,13 @@ test = ["flaky", "ipykernel (>=6.19.3)", "ipython", "ipywidgets", "nbconvert (>= [[package]] name = "nbconvert" -version = "7.14.2" +version = "7.15.0" description = "Converting Jupyter Notebooks" optional = false python-versions = ">=3.8" files = [ - {file = "nbconvert-7.14.2-py3-none-any.whl", hash = "sha256:db28590cef90f7faf2ebbc71acd402cbecf13d29176df728c0a9025a49345ea1"}, - {file = "nbconvert-7.14.2.tar.gz", hash = "sha256:a7f8808fd4e082431673ac538400218dd45efd076fbeb07cc6e5aa5a3a4e949e"}, + {file = "nbconvert-7.15.0-py3-none-any.whl", hash = "sha256:0efd3ca74fd1525560e0312cec235e57dfbf3c5c775c7e61e04c532b28f8da6f"}, + {file = "nbconvert-7.15.0.tar.gz", hash = "sha256:ff3f54a1a5e1e024beb9fde8946d05b6d0bf68cd14b5f2f9dc5b545c8bc71055"}, ] [package.dependencies] @@ -2134,13 +2191,13 @@ files = [ [[package]] name = "publicsuffixlist" -version = "0.10.0.20240201" +version = "0.10.0.20240205" description = "publicsuffixlist implement" optional = true python-versions = ">=2.6" files = [ - {file = "publicsuffixlist-0.10.0.20240201-py2.py3-none-any.whl", hash = "sha256:8cd17d60d8a62a8a5dc37b5a75ffc9fa15c45070a27f114919c5d7c79985b1a7"}, - {file = "publicsuffixlist-0.10.0.20240201.tar.gz", hash = "sha256:f0801faf9e545acb2dcb2a05af9289580b54d4b9c082e100c14496b6cfe22b5a"}, + {file = "publicsuffixlist-0.10.0.20240205-py2.py3-none-any.whl", hash = "sha256:d8d15322b3813b0c34cbe13c6f626f85d7f89f0cb30de5c54f46508446510e0e"}, + {file = "publicsuffixlist-0.10.0.20240205.tar.gz", hash = "sha256:cc7ab0562c25180aa53aec8fe3b4a47312aefaf15016201f593d0df94628cea1"}, ] [package.extras] @@ -3581,4 +3638,4 @@ virustotal = ["validators"] [metadata] lock-version = "2.0" python-versions = "^3.8" -content-hash = "8a8f5f6d17bf8b927917f138ec3c0148911f34f6588812efade205852690dd9e" +content-hash = "7ea3385d8df23839eede81f7cc92e575ac04aa036ea15f2516ca6721b76db6b9" diff --git a/pymisp/__init__.py b/pymisp/__init__.py index a235ce9..3e20076 100644 --- a/pymisp/__init__.py +++ b/pymisp/__init__.py @@ -47,7 +47,6 @@ try: from .tools import update_objects # noqa from .api import PyMISP, register_user # noqa - from .api import PyMISP as ExpandedPyMISP # noqa from .tools import load_warninglists # noqa # Let's not bother with old python try: @@ -62,6 +61,11 @@ try: except ImportError as e: logger.warning(f'Unable to load pymisp properly: {e}') + +class ExpandedPyMISP(PyMISP): + warnings.warn('This class is deprecated, use PyMISP instead', FutureWarning) + + __all__ = ['PyMISP', 'register_user', 'AbstractMISP', 'MISPTag', 'MISPEvent', 'MISPAttribute', 'MISPObjectReference', 'MISPObjectAttribute', 'MISPObject', 'MISPUser', 'MISPOrganisation', 'MISPSighting', 'MISPLog', @@ -73,5 +77,5 @@ __all__ = ['PyMISP', 'register_user', 'AbstractMISP', 'MISPTag', 'MISPGalaxyClusterRelation', 'PyMISPError', 'NewEventError', 'NewAttributeError', 'NoURL', 'NoKey', 'InvalidMISPObject', 'UnknownMISPObjectTemplate', 'PyMISPInvalidFormat', 'EmailObject', 'FileObject', 'IPObject', 'DomainObject', 'URIObject', 'ASNObject', - 'Distribution', 'ThreatLevel', 'Analysis' + 'Distribution', 'ThreatLevel', 'Analysis', 'ExpandedPyMISP' ] diff --git a/pyproject.toml b/pyproject.toml index 803782f..2913e54 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "pymisp" -version = "2.4.184" +version = "2.4.184.1" description = "Python API for MISP." authors = ["Raphaël Vinot "] license = "BSD-2-Clause" @@ -82,7 +82,7 @@ ipython = [ {version = "^8.18.0", python = ">=3.9"}, {version = "^8.19.0", python = ">=3.10"} ] -jupyterlab = "^4.0.12" +jupyterlab = "^4.1.0" types-requests = "^2.31.0.20240125" types-python-dateutil = "^2.8.19.20240106" types-redis = "^4.6.0.20240106" From 1e4c9615fb8100bba613bb7b125f41a9de2e1d56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Vinot?= Date: Tue, 6 Feb 2024 14:48:15 +0100 Subject: [PATCH 69/80] chg: Bump changelog --- CHANGELOG.txt | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 638163e..5098b94 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -2,6 +2,14 @@ Changelog ========= +v2.4.184.1 (2024-02-06) +----------------------- + +Changes +~~~~~~~ +- Re-add ExpandedPyMISP, with a warning. [Raphaël Vinot] + + v2.4.184 (2024-02-02) --------------------- @@ -17,6 +25,7 @@ New Changes ~~~~~~~ +- Bump changelog. [Raphaël Vinot] - Bump deps, version, objects. [Raphaël Vinot] - Remove IntEnum. [Raphaël Vinot] - Add even more debug for gha. [Raphaël Vinot] From c9d6d047028ba3b5ea48f03c43f1fec2a832de22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Vinot?= Date: Tue, 6 Feb 2024 16:40:49 +0100 Subject: [PATCH 70/80] fix: Do not throw a warning every time one import pymisp... --- pymisp/__init__.py | 5 ++++- pyproject.toml | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/pymisp/__init__.py b/pymisp/__init__.py index 3e20076..73cdac6 100644 --- a/pymisp/__init__.py +++ b/pymisp/__init__.py @@ -63,7 +63,10 @@ except ImportError as e: class ExpandedPyMISP(PyMISP): - warnings.warn('This class is deprecated, use PyMISP instead', FutureWarning) + + def __init__(self, *args, **kwargs): + warnings.warn('This class is deprecated, use PyMISP instead', FutureWarning) + super().__init__(*args, **kwargs) __all__ = ['PyMISP', 'register_user', 'AbstractMISP', 'MISPTag', diff --git a/pyproject.toml b/pyproject.toml index 2913e54..938d296 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "pymisp" -version = "2.4.184.1" +version = "2.4.184.2" description = "Python API for MISP." authors = ["Raphaël Vinot "] license = "BSD-2-Clause" From 0c39ab2006d91b0416e8698fcee8bc3d26cb0647 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Vinot?= Date: Tue, 6 Feb 2024 16:42:33 +0100 Subject: [PATCH 71/80] chg: Add changelog --- CHANGELOG.txt | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 5098b94..b63b7d9 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -2,11 +2,42 @@ Changelog ========= +v2.4.184.2 (2024-02-06) +----------------------- + +Changes +~~~~~~~ +- Bump changelog. [Raphaël Vinot] +- Re-add ExpandedPyMISP, with a warning. [Raphaël Vinot] + +Fix +~~~ +- Do not throw a warning every time one import pymisp... [Raphaël Vinot] + +Other +~~~~~ +- Build(deps): bump codecov/codecov-action from 3 to 4. + [dependabot[bot]] + + Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 3 to 4. + - [Release notes](https://github.com/codecov/codecov-action/releases) + - [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md) + - [Commits](https://github.com/codecov/codecov-action/compare/v3...v4) + + --- + updated-dependencies: + - dependency-name: codecov/codecov-action + dependency-type: direct:production + update-type: version-update:semver-major + ... + + v2.4.184.1 (2024-02-06) ----------------------- Changes ~~~~~~~ +- Bump changelog. [Raphaël Vinot] - Re-add ExpandedPyMISP, with a warning. [Raphaël Vinot] From c84afb92d5d334dfa8eeb11e23d5d7514dcff9e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Vinot?= Date: Mon, 12 Feb 2024 11:35:24 +0100 Subject: [PATCH 72/80] fix: remove from __all__ entries that shouldn't be there --- pymisp/__init__.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/pymisp/__init__.py b/pymisp/__init__.py index 73cdac6..73f1be8 100644 --- a/pymisp/__init__.py +++ b/pymisp/__init__.py @@ -40,15 +40,14 @@ try: MISPEventDelegation, MISPUserSetting, MISPInbox, MISPEventBlocklist, MISPOrganisationBlocklist, MISPEventReport, MISPCorrelationExclusion, MISPDecayingModel, MISPGalaxy, MISPGalaxyCluster, MISPGalaxyClusterElement, MISPGalaxyClusterRelation) + from .api import PyMISP, register_user # noqa + # NOTE: the direct imports to .tools are kept for backward compatibility but should be removed in the future from .tools import AbstractMISPObjectGenerator # noqa - from .tools import Neo4j # noqa from .tools import openioc # noqa from .tools import ext_lookups # noqa from .tools import update_objects # noqa - - from .api import PyMISP, register_user # noqa from .tools import load_warninglists # noqa - # Let's not bother with old python + try: from .tools import reportlab_generator # noqa except ImportError: @@ -79,6 +78,5 @@ __all__ = ['PyMISP', 'register_user', 'AbstractMISP', 'MISPTag', 'MISPDecayingModel', 'MISPGalaxy', 'MISPGalaxyCluster', 'MISPGalaxyClusterElement', 'MISPGalaxyClusterRelation', 'PyMISPError', 'NewEventError', 'NewAttributeError', 'NoURL', 'NoKey', 'InvalidMISPObject', 'UnknownMISPObjectTemplate', 'PyMISPInvalidFormat', - 'EmailObject', 'FileObject', 'IPObject', 'DomainObject', 'URIObject', 'ASNObject', 'Distribution', 'ThreatLevel', 'Analysis', 'ExpandedPyMISP' ] From e6cb8552c564fca4daeddd636ce9ca38cfa19117 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Vinot?= Date: Mon, 12 Feb 2024 11:41:08 +0100 Subject: [PATCH 73/80] fix: Properly get body from message, without headers --- examples/add_email_object.py | 5 ++--- pymisp/tools/emailobject.py | 7 ++++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/examples/add_email_object.py b/examples/add_email_object.py index 756a562..5f190ae 100755 --- a/examples/add_email_object.py +++ b/examples/add_email_object.py @@ -1,7 +1,6 @@ #!/usr/bin/env python3 -# -*- coding: utf-8 -*- -from pymisp import ExpandedPyMISP +from pymisp import PyMISP from pymisp.tools import EMailObject import traceback from keys import misp_url, misp_key, misp_verifycert # type: ignore @@ -15,7 +14,7 @@ if __name__ == '__main__': parser.add_argument("-p", "--path", required=True, help="Path to process (expanded using glob).") args = parser.parse_args() - pymisp = ExpandedPyMISP(misp_url, misp_key, misp_verifycert, debug=True) + pymisp = PyMISP(misp_url, misp_key, misp_verifycert, debug=True) for f in glob.glob(args.path): try: diff --git a/pymisp/tools/emailobject.py b/pymisp/tools/emailobject.py index 731a3bc..4042f6e 100644 --- a/pymisp/tools/emailobject.py +++ b/pymisp/tools/emailobject.py @@ -20,7 +20,7 @@ from RTFDE.exceptions import MalformedEncapsulatedRtf, NotEncapsulatedRtf # typ from RTFDE.deencapsulate import DeEncapsulator # type: ignore from oletools.common.codepages import codepage2codec # type: ignore -from ..exceptions import InvalidMISPObject, PyMISPNotImplementedYet, MISPObjectException, NewAttributeError +from ..exceptions import InvalidMISPObject, MISPObjectException, NewAttributeError from .abstractgenerator import AbstractMISPObjectGenerator logger = logging.getLogger('pymisp') @@ -269,13 +269,14 @@ class EMailObject(AbstractMISPObjectGenerator): data=self.raw_emails.get('msg')) message = self.email + body: EmailMessage if body := message.get_body(preferencelist=['plain']): comment = f"{body.get_content_type()} body" if self.encapsulated_body == body.get_content_type(): comment += " De-Encapsulated from RTF in original msg." self.add_attribute("email-body", - body.as_string(), + body.get_content(), comment=comment) if body := message.get_body(preferencelist=['html']): @@ -283,7 +284,7 @@ class EMailObject(AbstractMISPObjectGenerator): if self.encapsulated_body == body.get_content_type(): comment += " De-Encapsulated from RTF in original msg." self.add_attribute("email-body", - body.as_string(), + body.get_content(), comment=comment) headers = [f"{k}: {v}" for k, v in message.items()] From b5d953c3e1de9ea7c7e57bf71e6eae52fbfcc017 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Vinot?= Date: Mon, 12 Feb 2024 11:46:34 +0100 Subject: [PATCH 74/80] chg: Bump deps --- poetry.lock | 142 +++++++++++++++++++++++++------------------------ pyproject.toml | 6 +-- 2 files changed, 76 insertions(+), 72 deletions(-) diff --git a/poetry.lock b/poetry.lock index 8b7281b..d5c3921 100644 --- a/poetry.lock +++ b/poetry.lock @@ -763,29 +763,33 @@ test-randomorder = ["pytest-randomly"] [[package]] name = "debugpy" -version = "1.8.0" +version = "1.8.1" description = "An implementation of the Debug Adapter Protocol for Python" optional = false python-versions = ">=3.8" files = [ - {file = "debugpy-1.8.0-cp310-cp310-macosx_11_0_x86_64.whl", hash = "sha256:7fb95ca78f7ac43393cd0e0f2b6deda438ec7c5e47fa5d38553340897d2fbdfb"}, - {file = "debugpy-1.8.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ef9ab7df0b9a42ed9c878afd3eaaff471fce3fa73df96022e1f5c9f8f8c87ada"}, - {file = "debugpy-1.8.0-cp310-cp310-win32.whl", hash = "sha256:a8b7a2fd27cd9f3553ac112f356ad4ca93338feadd8910277aff71ab24d8775f"}, - {file = "debugpy-1.8.0-cp310-cp310-win_amd64.whl", hash = "sha256:5d9de202f5d42e62f932507ee8b21e30d49aae7e46d5b1dd5c908db1d7068637"}, - {file = "debugpy-1.8.0-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:ef54404365fae8d45cf450d0544ee40cefbcb9cb85ea7afe89a963c27028261e"}, - {file = "debugpy-1.8.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:60009b132c91951354f54363f8ebdf7457aeb150e84abba5ae251b8e9f29a8a6"}, - {file = "debugpy-1.8.0-cp311-cp311-win32.whl", hash = "sha256:8cd0197141eb9e8a4566794550cfdcdb8b3db0818bdf8c49a8e8f8053e56e38b"}, - {file = "debugpy-1.8.0-cp311-cp311-win_amd64.whl", hash = "sha256:a64093656c4c64dc6a438e11d59369875d200bd5abb8f9b26c1f5f723622e153"}, - {file = "debugpy-1.8.0-cp38-cp38-macosx_11_0_x86_64.whl", hash = "sha256:b05a6b503ed520ad58c8dc682749113d2fd9f41ffd45daec16e558ca884008cd"}, - {file = "debugpy-1.8.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3c6fb41c98ec51dd010d7ed650accfd07a87fe5e93eca9d5f584d0578f28f35f"}, - {file = "debugpy-1.8.0-cp38-cp38-win32.whl", hash = "sha256:46ab6780159eeabb43c1495d9c84cf85d62975e48b6ec21ee10c95767c0590aa"}, - {file = "debugpy-1.8.0-cp38-cp38-win_amd64.whl", hash = "sha256:bdc5ef99d14b9c0fcb35351b4fbfc06ac0ee576aeab6b2511702e5a648a2e595"}, - {file = "debugpy-1.8.0-cp39-cp39-macosx_11_0_x86_64.whl", hash = "sha256:61eab4a4c8b6125d41a34bad4e5fe3d2cc145caecd63c3fe953be4cc53e65bf8"}, - {file = "debugpy-1.8.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:125b9a637e013f9faac0a3d6a82bd17c8b5d2c875fb6b7e2772c5aba6d082332"}, - {file = "debugpy-1.8.0-cp39-cp39-win32.whl", hash = "sha256:57161629133113c97b387382045649a2b985a348f0c9366e22217c87b68b73c6"}, - {file = "debugpy-1.8.0-cp39-cp39-win_amd64.whl", hash = "sha256:e3412f9faa9ade82aa64a50b602544efcba848c91384e9f93497a458767e6926"}, - {file = "debugpy-1.8.0-py2.py3-none-any.whl", hash = "sha256:9c9b0ac1ce2a42888199df1a1906e45e6f3c9555497643a85e0bf2406e3ffbc4"}, - {file = "debugpy-1.8.0.zip", hash = "sha256:12af2c55b419521e33d5fb21bd022df0b5eb267c3e178f1d374a63a2a6bdccd0"}, + {file = "debugpy-1.8.1-cp310-cp310-macosx_11_0_x86_64.whl", hash = "sha256:3bda0f1e943d386cc7a0e71bfa59f4137909e2ed947fb3946c506e113000f741"}, + {file = "debugpy-1.8.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dda73bf69ea479c8577a0448f8c707691152e6c4de7f0c4dec5a4bc11dee516e"}, + {file = "debugpy-1.8.1-cp310-cp310-win32.whl", hash = "sha256:3a79c6f62adef994b2dbe9fc2cc9cc3864a23575b6e387339ab739873bea53d0"}, + {file = "debugpy-1.8.1-cp310-cp310-win_amd64.whl", hash = "sha256:7eb7bd2b56ea3bedb009616d9e2f64aab8fc7000d481faec3cd26c98a964bcdd"}, + {file = "debugpy-1.8.1-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:016a9fcfc2c6b57f939673c874310d8581d51a0fe0858e7fac4e240c5eb743cb"}, + {file = "debugpy-1.8.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fd97ed11a4c7f6d042d320ce03d83b20c3fb40da892f994bc041bbc415d7a099"}, + {file = "debugpy-1.8.1-cp311-cp311-win32.whl", hash = "sha256:0de56aba8249c28a300bdb0672a9b94785074eb82eb672db66c8144fff673146"}, + {file = "debugpy-1.8.1-cp311-cp311-win_amd64.whl", hash = "sha256:1a9fe0829c2b854757b4fd0a338d93bc17249a3bf69ecf765c61d4c522bb92a8"}, + {file = "debugpy-1.8.1-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:3ebb70ba1a6524d19fa7bb122f44b74170c447d5746a503e36adc244a20ac539"}, + {file = "debugpy-1.8.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a2e658a9630f27534e63922ebf655a6ab60c370f4d2fc5c02a5b19baf4410ace"}, + {file = "debugpy-1.8.1-cp312-cp312-win32.whl", hash = "sha256:caad2846e21188797a1f17fc09c31b84c7c3c23baf2516fed5b40b378515bbf0"}, + {file = "debugpy-1.8.1-cp312-cp312-win_amd64.whl", hash = "sha256:edcc9f58ec0fd121a25bc950d4578df47428d72e1a0d66c07403b04eb93bcf98"}, + {file = "debugpy-1.8.1-cp38-cp38-macosx_11_0_x86_64.whl", hash = "sha256:7a3afa222f6fd3d9dfecd52729bc2e12c93e22a7491405a0ecbf9e1d32d45b39"}, + {file = "debugpy-1.8.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d915a18f0597ef685e88bb35e5d7ab968964b7befefe1aaea1eb5b2640b586c7"}, + {file = "debugpy-1.8.1-cp38-cp38-win32.whl", hash = "sha256:92116039b5500633cc8d44ecc187abe2dfa9b90f7a82bbf81d079fcdd506bae9"}, + {file = "debugpy-1.8.1-cp38-cp38-win_amd64.whl", hash = "sha256:e38beb7992b5afd9d5244e96ad5fa9135e94993b0c551ceebf3fe1a5d9beb234"}, + {file = "debugpy-1.8.1-cp39-cp39-macosx_11_0_x86_64.whl", hash = "sha256:bfb20cb57486c8e4793d41996652e5a6a885b4d9175dd369045dad59eaacea42"}, + {file = "debugpy-1.8.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:efd3fdd3f67a7e576dd869c184c5dd71d9aaa36ded271939da352880c012e703"}, + {file = "debugpy-1.8.1-cp39-cp39-win32.whl", hash = "sha256:58911e8521ca0c785ac7a0539f1e77e0ce2df753f786188f382229278b4cdf23"}, + {file = "debugpy-1.8.1-cp39-cp39-win_amd64.whl", hash = "sha256:6df9aa9599eb05ca179fb0b810282255202a66835c6efb1d112d21ecb830ddd3"}, + {file = "debugpy-1.8.1-py2.py3-none-any.whl", hash = "sha256:28acbe2241222b87e255260c76741e1fbf04fdc3b6d094fcf57b6c6f75ce1242"}, + {file = "debugpy-1.8.1.zip", hash = "sha256:f696d6be15be87aef621917585f9bb94b1dc9e8aced570db1b8a6fc14e8f9b42"}, ] [[package]] @@ -1067,13 +1071,13 @@ files = [ [[package]] name = "ipykernel" -version = "6.29.1" +version = "6.29.2" description = "IPython Kernel for Jupyter" optional = false python-versions = ">=3.8" files = [ - {file = "ipykernel-6.29.1-py3-none-any.whl", hash = "sha256:e5dfba210fc9da74a5dae8fa6c41f816e11bd18d10381b2517d9a0d57cc987c4"}, - {file = "ipykernel-6.29.1.tar.gz", hash = "sha256:1547352b32da95a2761011a8dac2af930c26a0703dfa07690d16b7d74dac0ba1"}, + {file = "ipykernel-6.29.2-py3-none-any.whl", hash = "sha256:50384f5c577a260a1d53f1f59a828c7266d321c9b7d00d345693783f66616055"}, + {file = "ipykernel-6.29.2.tar.gz", hash = "sha256:3bade28004e3ff624ed57974948116670604ac5f676d12339693f3142176d3f0"}, ] [package.dependencies] @@ -1559,41 +1563,41 @@ regex = ["regex"] [[package]] name = "lief" -version = "0.14.0" +version = "0.14.1" description = "Library to instrument executable formats" optional = true python-versions = ">=3.8" files = [ - {file = "lief-0.14.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:b1e9af189e0dcbd6ce9ce67266135ef288c9b8f9a5efe2a47d0d0266288713cf"}, - {file = "lief-0.14.0-cp310-cp310-macosx_11_0_x86_64.whl", hash = "sha256:60be24af0b913a79922a9730302df5f380954a1d7b1c0c7de91b8918e36f0756"}, - {file = "lief-0.14.0-cp310-cp310-manylinux2014_aarch64.whl", hash = "sha256:1d949c53f95132ef0d218e88c3c982610c54426249c95f99b736e5c15bb1b75b"}, - {file = "lief-0.14.0-cp310-cp310-manylinux_2_28_x86_64.manylinux_2_27_x86_64.whl", hash = "sha256:51e7adfe1cc574a035b47a280cb5902cec6deb2d78ef0b47c536bdd75dfa6956"}, - {file = "lief-0.14.0-cp310-cp310-win32.whl", hash = "sha256:b34708c002c119f43998af3c4f219d06de6b66a34aceb298fd8bba8247e57572"}, - {file = "lief-0.14.0-cp310-cp310-win_amd64.whl", hash = "sha256:684c1500fddab8aaf5a4f74cd092ea190c4c837d31c5d087c68a9f175775c2db"}, - {file = "lief-0.14.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:737bd6fab74e222968936794e09b2bf399417c38a3bc13d6ad70836793e78586"}, - {file = "lief-0.14.0-cp311-cp311-macosx_11_0_x86_64.whl", hash = "sha256:ff42aa1f12d3dc8bc5641eb1991269fb92e43bae386559ad576c97ffa09639f2"}, - {file = "lief-0.14.0-cp311-cp311-manylinux2014_aarch64.whl", hash = "sha256:69df631cd0573388fa6891277d006f8da2fa42a5bbe3acc440b66a7352f6bef3"}, - {file = "lief-0.14.0-cp311-cp311-manylinux_2_28_x86_64.manylinux_2_27_x86_64.whl", hash = "sha256:b850f38b62ca8a92c7f9803ceac0e79369b732a75e627cba3c2b8f1fa729f643"}, - {file = "lief-0.14.0-cp311-cp311-win32.whl", hash = "sha256:ba29aabd72e92334d54883d58b108f80465973edaec3e27cb422abbc657bfe17"}, - {file = "lief-0.14.0-cp311-cp311-win_amd64.whl", hash = "sha256:33f2afdf9f00a8a208d5f32135834fc5f02bd12e8b14f0857cf14d4475ad03bb"}, - {file = "lief-0.14.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:70b53498390e8b95d878598c95bd068f5c86cab415c3869538fbce4cee36a9cc"}, - {file = "lief-0.14.0-cp312-cp312-macosx_11_0_x86_64.whl", hash = "sha256:c49d34c9140a4b77046137ceeeb872f26262447f514ccbf0cc985a91e59e7f69"}, - {file = "lief-0.14.0-cp312-cp312-manylinux2014_aarch64.whl", hash = "sha256:46808f2ec6903d8a4a4a4975d664e70c64ca11691bacb391a51029a8cb941e92"}, - {file = "lief-0.14.0-cp312-cp312-manylinux_2_28_x86_64.manylinux_2_27_x86_64.whl", hash = "sha256:4e6ca44bc9d0d314ac73148c64e4f9182c950a2f2024ab9d3d7100635d46261a"}, - {file = "lief-0.14.0-cp312-cp312-win32.whl", hash = "sha256:17e2809fa52e377d1a5045dbbbdea8bebbaad7f672d6c133287388e7e9942b64"}, - {file = "lief-0.14.0-cp312-cp312-win_amd64.whl", hash = "sha256:5713e27ba7bbe7c8c503354f3555a33e69d5236a02dd34d162156cc85a9b88b5"}, - {file = "lief-0.14.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:9998bd60d332b50f72fb71d22316b227f9fdbb301c953e8aa003822a80a6ed0a"}, - {file = "lief-0.14.0-cp38-cp38-macosx_11_0_x86_64.whl", hash = "sha256:fe783a180d63aa3ae19c5f58dc76afc179f40249c4c77d9f70bc557255b4051b"}, - {file = "lief-0.14.0-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:28e847e8410b9101f49af0ae9d06e7cb2d0db64c47442ac4c79abf1b15b2c108"}, - {file = "lief-0.14.0-cp38-cp38-manylinux_2_28_x86_64.manylinux_2_27_x86_64.whl", hash = "sha256:4a44d5bd2462c9db68227ed9193243c412ce6153fe6a8e53782ff4210e4606ab"}, - {file = "lief-0.14.0-cp38-cp38-win32.whl", hash = "sha256:0a0754079d595c9e3ceffed9e32d309ed139b1433fad9ad37aaa35e6a8e67d70"}, - {file = "lief-0.14.0-cp38-cp38-win_amd64.whl", hash = "sha256:bc8647f050728c09645666765de6dcbc681df7b0b6bdcfb4cdbbb96a523d2eaa"}, - {file = "lief-0.14.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:7f89b8e3cc6aa01f50a8ed58d5aea89f6d767df7951fd050659e9617c1b4eb45"}, - {file = "lief-0.14.0-cp39-cp39-macosx_11_0_x86_64.whl", hash = "sha256:110705c186f2ddc13fc2fad0dc9d501742d785b934103fdf56e86a86bcbcac1d"}, - {file = "lief-0.14.0-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:0ba07f12c00950554d29495c3aef3740c44243d1c0d80a3f8dadf64c456a32e7"}, - {file = "lief-0.14.0-cp39-cp39-manylinux_2_28_x86_64.manylinux_2_27_x86_64.whl", hash = "sha256:f237042467f41bf0e64b051e780865f9aef958ddec1a358317cc259da2ec2a16"}, - {file = "lief-0.14.0-cp39-cp39-win32.whl", hash = "sha256:75c7daefe56ba91ad4fc0a5e6573ca3c79dea2e938787b285b31ac0c25c5e5c3"}, - {file = "lief-0.14.0-cp39-cp39-win_amd64.whl", hash = "sha256:583d37400c85dc80299db873d380c0901995ae03606f7de50fd3d0538e7a7860"}, + {file = "lief-0.14.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:7a9a94882f9af110fb01b4558a58941d2352b9a4ae3fef15570a3fab921ff462"}, + {file = "lief-0.14.1-cp310-cp310-macosx_11_0_x86_64.whl", hash = "sha256:bcc06f24f64fa6f20372d625ce60c40a7a6f669e11bdd02c2f0b8c5c6d09a5ee"}, + {file = "lief-0.14.1-cp310-cp310-manylinux2014_aarch64.whl", hash = "sha256:d22f804eee7f1b4a4b37e7a3d35e2003c4c054f3450d40389e54c8ac9fc2a5db"}, + {file = "lief-0.14.1-cp310-cp310-manylinux_2_28_x86_64.manylinux_2_27_x86_64.whl", hash = "sha256:26134815adecfd7f15dfbdf12cc64df25bcf3d0db917cf115fc3b296d09be496"}, + {file = "lief-0.14.1-cp310-cp310-win32.whl", hash = "sha256:6ca0220189698599df30b8044f43fb1fc7ba919fb9ef6047c892f9faee16393a"}, + {file = "lief-0.14.1-cp310-cp310-win_amd64.whl", hash = "sha256:c321234b50997c217107c09e69f53518c37fac637f8735c968c258dd4c748fb2"}, + {file = "lief-0.14.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3ca365c704c6b6b1ce631b92fea2eddaf93d66c897a0ec4ab51e9ab9e3345920"}, + {file = "lief-0.14.1-cp311-cp311-macosx_11_0_x86_64.whl", hash = "sha256:1f3c40eadff07a4c8fa74f1e268f9fa70b68f39b6795a00cd82160ca6782d5c3"}, + {file = "lief-0.14.1-cp311-cp311-manylinux2014_aarch64.whl", hash = "sha256:c202ed13b641db2e1f8a24743fb0c85595b32ea92cc3c517d3f7a9977e16dcb4"}, + {file = "lief-0.14.1-cp311-cp311-manylinux_2_28_x86_64.manylinux_2_27_x86_64.whl", hash = "sha256:fd481bfdfef04e8be4d200bca771d0d9394d9146c6cd403f9e58c80c4196a24e"}, + {file = "lief-0.14.1-cp311-cp311-win32.whl", hash = "sha256:473e9a37beef8db8bab1a777271aa49cce44dfe35af65cb8fad576377518c0bd"}, + {file = "lief-0.14.1-cp311-cp311-win_amd64.whl", hash = "sha256:24f687244e14d4a8307430babc5c712a1dd4e519172886ad4aeb9825f88f7569"}, + {file = "lief-0.14.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6df40e3750b8b26f88a6b28ac01db7338cdb6158f28363c755bf36452ce20d28"}, + {file = "lief-0.14.1-cp312-cp312-macosx_11_0_x86_64.whl", hash = "sha256:e7f7a55db2fcf269569f9e9fa5ea752620396de17bd9d29fc8b29e176975ecdb"}, + {file = "lief-0.14.1-cp312-cp312-manylinux2014_aarch64.whl", hash = "sha256:50795b51884b76a78c481d6d069d992561c217180bd81cf12554180389eff0a3"}, + {file = "lief-0.14.1-cp312-cp312-manylinux_2_28_x86_64.manylinux_2_27_x86_64.whl", hash = "sha256:497b88f9c9aaae999766ba188744ee35c5f38b4b64016f7dbb7037e9bf325382"}, + {file = "lief-0.14.1-cp312-cp312-win32.whl", hash = "sha256:08bad88083f696915f8dcda4042a3bfc514e17462924ec8984085838b2261921"}, + {file = "lief-0.14.1-cp312-cp312-win_amd64.whl", hash = "sha256:e131d6158a085f8a72124136816fefc29405c725cd3695ce22a904e471f0f815"}, + {file = "lief-0.14.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:df650fa05ca131e4dfeb42c77985e1eb239730af9944bc0aadb1dfac8576e0e8"}, + {file = "lief-0.14.1-cp38-cp38-macosx_11_0_x86_64.whl", hash = "sha256:b4e76eeb48ca2925c6ca6034d408582615f2faa855f9bb11482e7acbdecc4803"}, + {file = "lief-0.14.1-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:016e4fac91303466024154dd3c4b599e8b7c52882f72038b62a2be386d98c8f9"}, + {file = "lief-0.14.1-cp38-cp38-manylinux_2_28_x86_64.manylinux_2_27_x86_64.whl", hash = "sha256:9a5c7732a3ce53b306c8180ab64fdfb36d8cd9df91aedd9e2b4dad9faf47492b"}, + {file = "lief-0.14.1-cp38-cp38-win32.whl", hash = "sha256:7030c22a4446ea2ac673fd50128e9c639121c0a4dae11ca1cd8cc20d62d26e7e"}, + {file = "lief-0.14.1-cp38-cp38-win_amd64.whl", hash = "sha256:4a35ceeee74bb9bb4c7171f4bca814576a3aa6dec16a0a9469e5743db0a9ba0c"}, + {file = "lief-0.14.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:abb15e4de34e70661fd35e87e2634abf0ae57a8c8ac78d02ad4259f5a5817e26"}, + {file = "lief-0.14.1-cp39-cp39-macosx_11_0_x86_64.whl", hash = "sha256:33d062340c709c1a33539d221ea3cb764cbb8d7c9ee8aae28bf9797bc8715a0b"}, + {file = "lief-0.14.1-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:66deb1b26de43acb2fd0b2fc5e6be70093eaaa93797332cc4613e163164c77e7"}, + {file = "lief-0.14.1-cp39-cp39-manylinux_2_28_x86_64.manylinux_2_27_x86_64.whl", hash = "sha256:c1c15bd3e5b15da6dcc0ba75d5549f15bfbf9214c0d8e3938f85877a40c352d9"}, + {file = "lief-0.14.1-cp39-cp39-win32.whl", hash = "sha256:ebcbe4eadd33d8cf2c6015f44d6c9b72f81388af745938e633c4bb90262b2036"}, + {file = "lief-0.14.1-cp39-cp39-win_amd64.whl", hash = "sha256:2db3eb282a35daf51f89c6509226668a08fb6a6d1f507dd549dd9f077585db11"}, ] [[package]] @@ -1787,13 +1791,13 @@ test = ["flaky", "ipykernel (>=6.19.3)", "ipython", "ipywidgets", "nbconvert (>= [[package]] name = "nbconvert" -version = "7.15.0" +version = "7.16.0" description = "Converting Jupyter Notebooks" optional = false python-versions = ">=3.8" files = [ - {file = "nbconvert-7.15.0-py3-none-any.whl", hash = "sha256:0efd3ca74fd1525560e0312cec235e57dfbf3c5c775c7e61e04c532b28f8da6f"}, - {file = "nbconvert-7.15.0.tar.gz", hash = "sha256:ff3f54a1a5e1e024beb9fde8946d05b6d0bf68cd14b5f2f9dc5b545c8bc71055"}, + {file = "nbconvert-7.16.0-py3-none-any.whl", hash = "sha256:ad3dc865ea6e2768d31b7eb6c7ab3be014927216a5ece3ef276748dd809054c7"}, + {file = "nbconvert-7.16.0.tar.gz", hash = "sha256:813e6553796362489ae572e39ba1bff978536192fb518e10826b0e8cadf03ec8"}, ] [package.dependencies] @@ -2191,13 +2195,13 @@ files = [ [[package]] name = "publicsuffixlist" -version = "0.10.0.20240205" +version = "0.10.0.20240210" description = "publicsuffixlist implement" optional = true python-versions = ">=2.6" files = [ - {file = "publicsuffixlist-0.10.0.20240205-py2.py3-none-any.whl", hash = "sha256:d8d15322b3813b0c34cbe13c6f626f85d7f89f0cb30de5c54f46508446510e0e"}, - {file = "publicsuffixlist-0.10.0.20240205.tar.gz", hash = "sha256:cc7ab0562c25180aa53aec8fe3b4a47312aefaf15016201f593d0df94628cea1"}, + {file = "publicsuffixlist-0.10.0.20240210-py2.py3-none-any.whl", hash = "sha256:7b7092b3c13df4a10e73146a391604a36a090a13bc46344e09cdc784cf9a4606"}, + {file = "publicsuffixlist-0.10.0.20240210.tar.gz", hash = "sha256:535f5e2664430353b3cfa7fcd486d77a9b1749c7fbc8965089a35e72a76c60ae"}, ] [package.extras] @@ -2622,13 +2626,13 @@ rpds-py = ">=0.7.0" [[package]] name = "reportlab" -version = "4.0.9" +version = "4.1.0" description = "The Reportlab Toolkit" optional = true python-versions = ">=3.7,<4" files = [ - {file = "reportlab-4.0.9-py3-none-any.whl", hash = "sha256:c9656216321897486e323be138f7aea67851cedc116b8cc35f8ec7f8cc763538"}, - {file = "reportlab-4.0.9.tar.gz", hash = "sha256:f32bff66a0fda234202e1e33eaf77f25008871a61cb01cd91584a521a04c0047"}, + {file = "reportlab-4.1.0-py3-none-any.whl", hash = "sha256:28a40d5000afbd8ccae15a47f7abe2841768461354bede1a9d42841132997c98"}, + {file = "reportlab-4.1.0.tar.gz", hash = "sha256:3a99faf412691159c068b3ff01c15307ce2fd2cf6b860199434874e002040a84"}, ] [package.dependencies] @@ -2964,13 +2968,13 @@ test = ["cython (>=3.0)", "filelock", "html5lib", "pytest (>=4.6)", "setuptools [[package]] name = "sphinx-autodoc-typehints" -version = "1.25.3" +version = "2.0.0" description = "Type hints (PEP 484) support for the Sphinx autodoc extension" optional = true python-versions = ">=3.8" files = [ - {file = "sphinx_autodoc_typehints-1.25.3-py3-none-any.whl", hash = "sha256:d3da7fa9a9761eff6ff09f8b1956ae3090a2d4f4ad54aebcade8e458d6340835"}, - {file = "sphinx_autodoc_typehints-1.25.3.tar.gz", hash = "sha256:70db10b391acf4e772019765991d2de0ff30ec0899b9ba137706dc0b3c4835e0"}, + {file = "sphinx_autodoc_typehints-2.0.0-py3-none-any.whl", hash = "sha256:12c0e161f6fe191c2cdfd8fa3caea271f5387d9fbc67ebcd6f4f1f24ce880993"}, + {file = "sphinx_autodoc_typehints-2.0.0.tar.gz", hash = "sha256:7f2cdac2e70fd9787926b6e9e541cd4ded1e838d2b46fda2a1bb0a75ec5b7f3a"}, ] [package.dependencies] @@ -3384,13 +3388,13 @@ files = [ [[package]] name = "tzdata" -version = "2023.4" +version = "2024.1" description = "Provider of IANA time zone data" optional = true 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"}, + {file = "tzdata-2024.1-py2.py3-none-any.whl", hash = "sha256:9068bc196136463f5245e51efda838afa15aaeca9903f49050dfa2679db4d252"}, + {file = "tzdata-2024.1.tar.gz", hash = "sha256:2674120f8d891909751c38abcdfd386ac0a5a1127954fbc332af6b5ceae07efd"}, ] [[package]] @@ -3638,4 +3642,4 @@ virustotal = ["validators"] [metadata] lock-version = "2.0" python-versions = "^3.8" -content-hash = "7ea3385d8df23839eede81f7cc92e575ac04aa036ea15f2516ca6721b76db6b9" +content-hash = "38686d7ffa7a8e3771b882acf0f42d145419456c7779e01c7c67dd639867d00f" diff --git a/pyproject.toml b/pyproject.toml index 938d296..0a35a0a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -50,12 +50,12 @@ RTFDE = {version = "^0.1.1", optional = true} oletools = {version = "^0.60.1", optional = true} python-magic = {version = "^0.4.27", optional = true} pydeep2 = {version = "^0.5.1", optional = true} -lief = {version = "^0.14", optional = true} +lief = {version = "^0.14.1", optional = true} beautifulsoup4 = {version = "^4.12.3", optional = true} validators = {version = "^0.22.0", optional = true} -sphinx-autodoc-typehints = {version = "^1.25.3", optional = true} +sphinx-autodoc-typehints = {version = "^2.0.0", optional = true} recommonmark = {version = "^0.7.1", optional = true} -reportlab = {version = "^4.0.9", optional = true} +reportlab = {version = "^4.1.0", optional = true} pyfaup = {version = "^1.2", optional = true} publicsuffixlist = {version = "^0.10.0.20231214", optional = true} urllib3 = {extras = ["brotli"], version = "*", optional = true} From ccb7a5dc3ef2fa2afe4e1b964c7e9bd732216b53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Vinot?= Date: Mon, 12 Feb 2024 12:10:18 +0100 Subject: [PATCH 75/80] chg: Bump version --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 0a35a0a..16d11dd 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "pymisp" -version = "2.4.184.2" +version = "2.4.184.3" description = "Python API for MISP." authors = ["Raphaël Vinot "] license = "BSD-2-Clause" From 05beec393c5613c352dafdaeaf5dcf983bfb2d51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Vinot?= Date: Mon, 12 Feb 2024 12:11:37 +0100 Subject: [PATCH 76/80] chg: Bump changelog --- CHANGELOG.txt | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index b63b7d9..6db3c45 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -2,11 +2,42 @@ Changelog ========= +v2.4.184.3 (2024-02-12) +----------------------- + +Changes +~~~~~~~ +- Bump version. [Raphaël Vinot] +- Bump deps. [Raphaël Vinot] + +Fix +~~~ +- Properly get body from message, without headers. [Raphaël Vinot] +- Remove from __all__ entries that shouldn't be there. [Raphaël Vinot] + +Other +~~~~~ +- Build(deps-dev): bump jupyter-lsp from 2.2.1 to 2.2.2. + [dependabot[bot]] + + Bumps [jupyter-lsp](https://github.com/jupyter-lsp/jupyterlab-lsp) from 2.2.1 to 2.2.2. + - [Release notes](https://github.com/jupyter-lsp/jupyterlab-lsp/releases) + - [Changelog](https://github.com/jupyter-lsp/jupyterlab-lsp/blob/main/CHANGELOG.md) + - [Commits](https://github.com/jupyter-lsp/jupyterlab-lsp/commits) + + --- + updated-dependencies: + - dependency-name: jupyter-lsp + dependency-type: indirect + ... + + v2.4.184.2 (2024-02-06) ----------------------- Changes ~~~~~~~ +- Add changelog. [Raphaël Vinot] - Bump changelog. [Raphaël Vinot] - Re-add ExpandedPyMISP, with a warning. [Raphaël Vinot] From 7ee0d08b2fe467e338e4383935b8eaf60e3cd1dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Vinot?= Date: Fri, 16 Feb 2024 14:46:35 +0100 Subject: [PATCH 77/80] chg: Bump deps, version --- poetry.lock | 292 ++++++++++++++++++++++++++----------------------- pyproject.toml | 4 +- 2 files changed, 156 insertions(+), 140 deletions(-) diff --git a/poetry.lock b/poetry.lock index d5c3921..0da474d 100644 --- a/poetry.lock +++ b/poetry.lock @@ -725,27 +725,43 @@ toml = ["tomli"] [[package]] name = "cryptography" -version = "42.0.2" +version = "42.0.3" description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." optional = false python-versions = ">=3.7" files = [ - {file = "cryptography-42.0.2-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:701171f825dcab90969596ce2af253143b93b08f1a716d4b2a9d2db5084ef7be"}, - {file = "cryptography-42.0.2-cp37-abi3-macosx_10_12_x86_64.whl", hash = "sha256:61321672b3ac7aade25c40449ccedbc6db72c7f5f0fdf34def5e2f8b51ca530d"}, - {file = "cryptography-42.0.2-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ea2c3ffb662fec8bbbfce5602e2c159ff097a4631d96235fcf0fb00e59e3ece4"}, - {file = "cryptography-42.0.2-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3b15c678f27d66d247132cbf13df2f75255627bcc9b6a570f7d2fd08e8c081d2"}, - {file = "cryptography-42.0.2-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:36d4b7c4be6411f58f60d9ce555a73df8406d484ba12a63549c88bd64f7967f1"}, - {file = "cryptography-42.0.2-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:a00aee5d1b6c20620161984f8ab2ab69134466c51f58c052c11b076715e72929"}, - {file = "cryptography-42.0.2-cp37-abi3-win32.whl", hash = "sha256:4b063d3413f853e056161eb0c7724822a9740ad3caa24b8424d776cebf98e7ee"}, - {file = "cryptography-42.0.2-cp39-abi3-macosx_10_12_universal2.whl", hash = "sha256:55d1580e2d7e17f45d19d3b12098e352f3a37fe86d380bf45846ef257054b242"}, - {file = "cryptography-42.0.2-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b9097a208875fc7bbeb1286d0125d90bdfed961f61f214d3f5be62cd4ed8a446"}, - {file = "cryptography-42.0.2-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:fa3dec4ba8fb6e662770b74f62f1a0c7d4e37e25b58b2bf2c1be4c95372b4a33"}, - {file = "cryptography-42.0.2-cp39-abi3-win32.whl", hash = "sha256:3dbd37e14ce795b4af61b89b037d4bc157f2cb23e676fa16932185a04dfbf635"}, - {file = "cryptography-42.0.2-cp39-abi3-win_amd64.whl", hash = "sha256:8a06641fb07d4e8f6c7dda4fc3f8871d327803ab6542e33831c7ccfdcb4d0ad6"}, - {file = "cryptography-42.0.2-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:a7ef8dd0bf2e1d0a27042b231a3baac6883cdd5557036f5e8df7139255feaac6"}, - {file = "cryptography-42.0.2-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:320948ab49883557a256eab46149df79435a22d2fefd6a66fe6946f1b9d9d008"}, - {file = "cryptography-42.0.2-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:52ed9ebf8ac602385126c9a2fe951db36f2cb0c2538d22971487f89d0de4065a"}, - {file = "cryptography-42.0.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:141e2aa5ba100d3788c0ad7919b288f89d1fe015878b9659b307c9ef867d3a65"}, + {file = "cryptography-42.0.3-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:de5086cd475d67113ccb6f9fae6d8fe3ac54a4f9238fd08bfdb07b03d791ff0a"}, + {file = "cryptography-42.0.3-cp37-abi3-macosx_10_12_x86_64.whl", hash = "sha256:935cca25d35dda9e7bd46a24831dfd255307c55a07ff38fd1a92119cffc34857"}, + {file = "cryptography-42.0.3-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:20100c22b298c9eaebe4f0b9032ea97186ac2555f426c3e70670f2517989543b"}, + {file = "cryptography-42.0.3-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2eb6368d5327d6455f20327fb6159b97538820355ec00f8cc9464d617caecead"}, + {file = "cryptography-42.0.3-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:39d5c93e95bcbc4c06313fc6a500cee414ee39b616b55320c1904760ad686938"}, + {file = "cryptography-42.0.3-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:3d96ea47ce6d0055d5b97e761d37b4e84195485cb5a38401be341fabf23bc32a"}, + {file = "cryptography-42.0.3-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:d1998e545081da0ab276bcb4b33cce85f775adb86a516e8f55b3dac87f469548"}, + {file = "cryptography-42.0.3-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:93fbee08c48e63d5d1b39ab56fd3fdd02e6c2431c3da0f4edaf54954744c718f"}, + {file = "cryptography-42.0.3-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:90147dad8c22d64b2ff7331f8d4cddfdc3ee93e4879796f837bdbb2a0b141e0c"}, + {file = "cryptography-42.0.3-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:4dcab7c25e48fc09a73c3e463d09ac902a932a0f8d0c568238b3696d06bf377b"}, + {file = "cryptography-42.0.3-cp37-abi3-win32.whl", hash = "sha256:1e935c2900fb53d31f491c0de04f41110351377be19d83d908c1fd502ae8daa5"}, + {file = "cryptography-42.0.3-cp37-abi3-win_amd64.whl", hash = "sha256:762f3771ae40e111d78d77cbe9c1035e886ac04a234d3ee0856bf4ecb3749d54"}, + {file = "cryptography-42.0.3-cp39-abi3-macosx_10_12_universal2.whl", hash = "sha256:0d3ec384058b642f7fb7e7bff9664030011ed1af8f852540c76a1317a9dd0d20"}, + {file = "cryptography-42.0.3-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:35772a6cffd1f59b85cb670f12faba05513446f80352fe811689b4e439b5d89e"}, + {file = "cryptography-42.0.3-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:04859aa7f12c2b5f7e22d25198ddd537391f1695df7057c8700f71f26f47a129"}, + {file = "cryptography-42.0.3-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:c3d1f5a1d403a8e640fa0887e9f7087331abb3f33b0f2207d2cc7f213e4a864c"}, + {file = "cryptography-42.0.3-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:df34312149b495d9d03492ce97471234fd9037aa5ba217c2a6ea890e9166f151"}, + {file = "cryptography-42.0.3-cp39-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:de4ae486041878dc46e571a4c70ba337ed5233a1344c14a0790c4c4be4bbb8b4"}, + {file = "cryptography-42.0.3-cp39-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:0fab2a5c479b360e5e0ea9f654bcebb535e3aa1e493a715b13244f4e07ea8eec"}, + {file = "cryptography-42.0.3-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:25b09b73db78facdfd7dd0fa77a3f19e94896197c86e9f6dc16bce7b37a96504"}, + {file = "cryptography-42.0.3-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:d5cf11bc7f0b71fb71af26af396c83dfd3f6eed56d4b6ef95d57867bf1e4ba65"}, + {file = "cryptography-42.0.3-cp39-abi3-win32.whl", hash = "sha256:0fea01527d4fb22ffe38cd98951c9044400f6eff4788cf52ae116e27d30a1ba3"}, + {file = "cryptography-42.0.3-cp39-abi3-win_amd64.whl", hash = "sha256:2619487f37da18d6826e27854a7f9d4d013c51eafb066c80d09c63cf24505306"}, + {file = "cryptography-42.0.3-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:ead69ba488f806fe1b1b4050febafdbf206b81fa476126f3e16110c818bac396"}, + {file = "cryptography-42.0.3-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:20180da1b508f4aefc101cebc14c57043a02b355d1a652b6e8e537967f1e1b46"}, + {file = "cryptography-42.0.3-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:5fbf0f3f0fac7c089308bd771d2c6c7b7d53ae909dce1db52d8e921f6c19bb3a"}, + {file = "cryptography-42.0.3-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:c23f03cfd7d9826cdcbad7850de67e18b4654179e01fe9bc623d37c2638eb4ef"}, + {file = "cryptography-42.0.3-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:db0480ffbfb1193ac4e1e88239f31314fe4c6cdcf9c0b8712b55414afbf80db4"}, + {file = "cryptography-42.0.3-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:6c25e1e9c2ce682d01fc5e2dde6598f7313027343bd14f4049b82ad0402e52cd"}, + {file = "cryptography-42.0.3-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:9541c69c62d7446539f2c1c06d7046aef822940d248fa4b8962ff0302862cc1f"}, + {file = "cryptography-42.0.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:1b797099d221df7cce5ff2a1d272761d1554ddf9a987d3e11f6459b38cd300fd"}, + {file = "cryptography-42.0.3.tar.gz", hash = "sha256:069d2ce9be5526a44093a0991c450fe9906cdf069e0e7cd67d9dee49a62b9ebe"}, ] [package.dependencies] @@ -956,13 +972,13 @@ files = [ [[package]] name = "httpcore" -version = "1.0.2" +version = "1.0.3" description = "A minimal low-level HTTP client." optional = false python-versions = ">=3.8" files = [ - {file = "httpcore-1.0.2-py3-none-any.whl", hash = "sha256:096cc05bca73b8e459a1fc3dcf585148f63e534eae4339559c9b8a8d6399acc7"}, - {file = "httpcore-1.0.2.tar.gz", hash = "sha256:9fc092e4799b26174648e54b74ed5f683132a464e95643b226e00c2ed2fa6535"}, + {file = "httpcore-1.0.3-py3-none-any.whl", hash = "sha256:9a6a501c3099307d9fd76ac244e08503427679b1e81ceb1d922485e2f2462ad2"}, + {file = "httpcore-1.0.3.tar.gz", hash = "sha256:5c0f9546ad17dac4d0772b0808856eb616eb8b48ce94f49ed819fd6982a8a544"}, ] [package.dependencies] @@ -973,7 +989,7 @@ h11 = ">=0.13,<0.15" asyncio = ["anyio (>=4.0,<5.0)"] http2 = ["h2 (>=3,<5)"] socks = ["socksio (==1.*)"] -trio = ["trio (>=0.22.0,<0.23.0)"] +trio = ["trio (>=0.22.0,<0.24.0)"] [[package]] name = "httpx" @@ -1475,13 +1491,13 @@ test = ["jupyter-server (>=2.0.0)", "pytest (>=7.0)", "pytest-jupyter[server] (> [[package]] name = "jupyterlab" -version = "4.1.0" +version = "4.1.1" description = "JupyterLab computational environment" optional = false python-versions = ">=3.8" files = [ - {file = "jupyterlab-4.1.0-py3-none-any.whl", hash = "sha256:5380e85fb4f11a227ed2db13103e513cfea274d1011f6210e62d611e92e0369d"}, - {file = "jupyterlab-4.1.0.tar.gz", hash = "sha256:92cdfd86c53e163fb9e91e14497901153536c5a889c9225dade270f6107a077f"}, + {file = "jupyterlab-4.1.1-py3-none-any.whl", hash = "sha256:fa3e8c18b804eac04e51ceebd9dd3dd396e08106816f0d09cc426799d7087632"}, + {file = "jupyterlab-4.1.1.tar.gz", hash = "sha256:8acc9f561729d8f32c14c294c397917cddfeeb13a5d46f811979b71b4911a9fd"}, ] [package.dependencies] @@ -1502,7 +1518,7 @@ tornado = ">=6.2.0" traitlets = "*" [package.extras] -dev = ["build", "bump2version", "coverage", "hatch", "pre-commit", "pytest-cov", "ruff (==0.1.15)"] +dev = ["build", "bump2version", "coverage", "hatch", "pre-commit", "pytest-cov", "ruff (==0.2.0)"] docs = ["jsx-lexer", "myst-parser", "pydata-sphinx-theme (>=0.13.0)", "pytest", "pytest-check-links", "pytest-jupyter", "sphinx (>=1.8,<7.3.0)", "sphinx-copybutton"] docs-screenshots = ["altair (==5.2.0)", "ipython (==8.16.1)", "ipywidgets (==8.1.1)", "jupyterlab-geojson (==3.4.0)", "jupyterlab-language-pack-zh-cn (==4.0.post6)", "matplotlib (==3.8.2)", "nbconvert (>=7.0.0)", "pandas (==2.2.0)", "scipy (==1.12.0)", "vega-datasets (==0.9.0)"] test = ["coverage", "pytest (>=7.0)", "pytest-check-links (>=0.7)", "pytest-console-scripts", "pytest-cov", "pytest-jupyter (>=0.5.3)", "pytest-timeout", "pytest-tornasync", "requests", "requests-cache", "virtualenv"] @@ -1520,13 +1536,13 @@ files = [ [[package]] name = "jupyterlab-server" -version = "2.25.2" +version = "2.25.3" description = "A set of server components for JupyterLab and JupyterLab like applications." optional = false python-versions = ">=3.8" files = [ - {file = "jupyterlab_server-2.25.2-py3-none-any.whl", hash = "sha256:5b1798c9cc6a44f65c757de9f97fc06fc3d42535afbf47d2ace5e964ab447aaf"}, - {file = "jupyterlab_server-2.25.2.tar.gz", hash = "sha256:bd0ec7a99ebcedc8bcff939ef86e52c378e44c2707e053fcd81d046ce979ee63"}, + {file = "jupyterlab_server-2.25.3-py3-none-any.whl", hash = "sha256:c48862519fded9b418c71645d85a49b2f0ec50d032ba8316738e9276046088c1"}, + {file = "jupyterlab_server-2.25.3.tar.gz", hash = "sha256:846f125a8a19656611df5b03e5912c8393cea6900859baa64fa515eb64a8dc40"}, ] [package.dependencies] @@ -1861,13 +1877,13 @@ files = [ [[package]] name = "notebook-shim" -version = "0.2.3" +version = "0.2.4" description = "A shim layer for notebook traits and config" optional = false python-versions = ">=3.7" files = [ - {file = "notebook_shim-0.2.3-py3-none-any.whl", hash = "sha256:a83496a43341c1674b093bfcebf0fe8e74cbe7eda5fd2bbc56f8e39e1486c0c7"}, - {file = "notebook_shim-0.2.3.tar.gz", hash = "sha256:f69388ac283ae008cd506dda10d0288b09a017d822d5e8c7129a152cbd3ce7e9"}, + {file = "notebook_shim-0.2.4-py3-none-any.whl", hash = "sha256:411a5be4e9dc882a074ccbcae671eda64cceb068767e9a3419096986560e1cef"}, + {file = "notebook_shim-0.2.4.tar.gz", hash = "sha256:b4b2cfa1b65d98307ca24361f5b30fe785b53c3fd07b7a47e89acb5e6ac638cb"}, ] [package.dependencies] @@ -2128,13 +2144,13 @@ testing = ["pytest", "pytest-benchmark"] [[package]] name = "prometheus-client" -version = "0.19.0" +version = "0.20.0" description = "Python client for the Prometheus monitoring system." optional = false python-versions = ">=3.8" files = [ - {file = "prometheus_client-0.19.0-py3-none-any.whl", hash = "sha256:c88b1e6ecf6b41cd8fb5731c7ae919bf66df6ec6fafa555cd6c0e16ca169ae92"}, - {file = "prometheus_client-0.19.0.tar.gz", hash = "sha256:4585b0d1223148c27a225b10dbec5ae9bc4c81a99a3fa80774fa6209935324e1"}, + {file = "prometheus_client-0.20.0-py3-none-any.whl", hash = "sha256:cde524a85bce83ca359cc837f28b8c0db5cac7aa653a588fd7e84ba061c329e7"}, + {file = "prometheus_client-0.20.0.tar.gz", hash = "sha256:287629d00b147a32dcb2be0b9df905da599b2d82f80377083ec8463309a4bb89"}, ] [package.extras] @@ -2195,13 +2211,13 @@ files = [ [[package]] name = "publicsuffixlist" -version = "0.10.0.20240210" +version = "0.10.0.20240214" description = "publicsuffixlist implement" optional = true python-versions = ">=2.6" files = [ - {file = "publicsuffixlist-0.10.0.20240210-py2.py3-none-any.whl", hash = "sha256:7b7092b3c13df4a10e73146a391604a36a090a13bc46344e09cdc784cf9a4606"}, - {file = "publicsuffixlist-0.10.0.20240210.tar.gz", hash = "sha256:535f5e2664430353b3cfa7fcd486d77a9b1749c7fbc8965089a35e72a76c60ae"}, + {file = "publicsuffixlist-0.10.0.20240214-py2.py3-none-any.whl", hash = "sha256:2c3b8da819571bb610328bda5b25d27fcbf6bc400896ca3c6502d291a16b32f4"}, + {file = "publicsuffixlist-0.10.0.20240214.tar.gz", hash = "sha256:45a206c5f9c1eccf138481280cfb0a67c2ccafc782ef89c7fd6dc6c4356230fe"}, ] [package.extras] @@ -2711,110 +2727,110 @@ files = [ [[package]] name = "rpds-py" -version = "0.17.1" +version = "0.18.0" description = "Python bindings to Rust's persistent data structures (rpds)" optional = false python-versions = ">=3.8" files = [ - {file = "rpds_py-0.17.1-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:4128980a14ed805e1b91a7ed551250282a8ddf8201a4e9f8f5b7e6225f54170d"}, - {file = "rpds_py-0.17.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ff1dcb8e8bc2261a088821b2595ef031c91d499a0c1b031c152d43fe0a6ecec8"}, - {file = "rpds_py-0.17.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d65e6b4f1443048eb7e833c2accb4fa7ee67cc7d54f31b4f0555b474758bee55"}, - {file = "rpds_py-0.17.1-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a71169d505af63bb4d20d23a8fbd4c6ce272e7bce6cc31f617152aa784436f29"}, - {file = "rpds_py-0.17.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:436474f17733c7dca0fbf096d36ae65277e8645039df12a0fa52445ca494729d"}, - {file = "rpds_py-0.17.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:10162fe3f5f47c37ebf6d8ff5a2368508fe22007e3077bf25b9c7d803454d921"}, - {file = "rpds_py-0.17.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:720215373a280f78a1814becb1312d4e4d1077b1202a56d2b0815e95ccb99ce9"}, - {file = "rpds_py-0.17.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:70fcc6c2906cfa5c6a552ba7ae2ce64b6c32f437d8f3f8eea49925b278a61453"}, - {file = "rpds_py-0.17.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:91e5a8200e65aaac342a791272c564dffcf1281abd635d304d6c4e6b495f29dc"}, - {file = "rpds_py-0.17.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:99f567dae93e10be2daaa896e07513dd4bf9c2ecf0576e0533ac36ba3b1d5394"}, - {file = "rpds_py-0.17.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:24e4900a6643f87058a27320f81336d527ccfe503984528edde4bb660c8c8d59"}, - {file = "rpds_py-0.17.1-cp310-none-win32.whl", hash = "sha256:0bfb09bf41fe7c51413f563373e5f537eaa653d7adc4830399d4e9bdc199959d"}, - {file = "rpds_py-0.17.1-cp310-none-win_amd64.whl", hash = "sha256:20de7b7179e2031a04042e85dc463a93a82bc177eeba5ddd13ff746325558aa6"}, - {file = "rpds_py-0.17.1-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:65dcf105c1943cba45d19207ef51b8bc46d232a381e94dd38719d52d3980015b"}, - {file = "rpds_py-0.17.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:01f58a7306b64e0a4fe042047dd2b7d411ee82e54240284bab63e325762c1147"}, - {file = "rpds_py-0.17.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:071bc28c589b86bc6351a339114fb7a029f5cddbaca34103aa573eba7b482382"}, - {file = "rpds_py-0.17.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ae35e8e6801c5ab071b992cb2da958eee76340e6926ec693b5ff7d6381441745"}, - {file = "rpds_py-0.17.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:149c5cd24f729e3567b56e1795f74577aa3126c14c11e457bec1b1c90d212e38"}, - {file = "rpds_py-0.17.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e796051f2070f47230c745d0a77a91088fbee2cc0502e9b796b9c6471983718c"}, - {file = "rpds_py-0.17.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:60e820ee1004327609b28db8307acc27f5f2e9a0b185b2064c5f23e815f248f8"}, - {file = "rpds_py-0.17.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1957a2ab607f9added64478a6982742eb29f109d89d065fa44e01691a20fc20a"}, - {file = "rpds_py-0.17.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8587fd64c2a91c33cdc39d0cebdaf30e79491cc029a37fcd458ba863f8815383"}, - {file = "rpds_py-0.17.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:4dc889a9d8a34758d0fcc9ac86adb97bab3fb7f0c4d29794357eb147536483fd"}, - {file = "rpds_py-0.17.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:2953937f83820376b5979318840f3ee47477d94c17b940fe31d9458d79ae7eea"}, - {file = "rpds_py-0.17.1-cp311-none-win32.whl", hash = "sha256:1bfcad3109c1e5ba3cbe2f421614e70439f72897515a96c462ea657261b96518"}, - {file = "rpds_py-0.17.1-cp311-none-win_amd64.whl", hash = "sha256:99da0a4686ada4ed0f778120a0ea8d066de1a0a92ab0d13ae68492a437db78bf"}, - {file = "rpds_py-0.17.1-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:1dc29db3900cb1bb40353772417800f29c3d078dbc8024fd64655a04ee3c4bdf"}, - {file = "rpds_py-0.17.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:82ada4a8ed9e82e443fcef87e22a3eed3654dd3adf6e3b3a0deb70f03e86142a"}, - {file = "rpds_py-0.17.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1d36b2b59e8cc6e576f8f7b671e32f2ff43153f0ad6d0201250a7c07f25d570e"}, - {file = "rpds_py-0.17.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3677fcca7fb728c86a78660c7fb1b07b69b281964673f486ae72860e13f512ad"}, - {file = "rpds_py-0.17.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:516fb8c77805159e97a689e2f1c80655c7658f5af601c34ffdb916605598cda2"}, - {file = "rpds_py-0.17.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:df3b6f45ba4515632c5064e35ca7f31d51d13d1479673185ba8f9fefbbed58b9"}, - {file = "rpds_py-0.17.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a967dd6afda7715d911c25a6ba1517975acd8d1092b2f326718725461a3d33f9"}, - {file = "rpds_py-0.17.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:dbbb95e6fc91ea3102505d111b327004d1c4ce98d56a4a02e82cd451f9f57140"}, - {file = "rpds_py-0.17.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:02866e060219514940342a1f84303a1ef7a1dad0ac311792fbbe19b521b489d2"}, - {file = "rpds_py-0.17.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:2528ff96d09f12e638695f3a2e0c609c7b84c6df7c5ae9bfeb9252b6fa686253"}, - {file = "rpds_py-0.17.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:bd345a13ce06e94c753dab52f8e71e5252aec1e4f8022d24d56decd31e1b9b23"}, - {file = "rpds_py-0.17.1-cp312-none-win32.whl", hash = "sha256:2a792b2e1d3038daa83fa474d559acfd6dc1e3650ee93b2662ddc17dbff20ad1"}, - {file = "rpds_py-0.17.1-cp312-none-win_amd64.whl", hash = "sha256:292f7344a3301802e7c25c53792fae7d1593cb0e50964e7bcdcc5cf533d634e3"}, - {file = "rpds_py-0.17.1-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:8ffe53e1d8ef2520ebcf0c9fec15bb721da59e8ef283b6ff3079613b1e30513d"}, - {file = "rpds_py-0.17.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:4341bd7579611cf50e7b20bb8c2e23512a3dc79de987a1f411cb458ab670eb90"}, - {file = "rpds_py-0.17.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2f4eb548daf4836e3b2c662033bfbfc551db58d30fd8fe660314f86bf8510b93"}, - {file = "rpds_py-0.17.1-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b686f25377f9c006acbac63f61614416a6317133ab7fafe5de5f7dc8a06d42eb"}, - {file = "rpds_py-0.17.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4e21b76075c01d65d0f0f34302b5a7457d95721d5e0667aea65e5bb3ab415c25"}, - {file = "rpds_py-0.17.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b86b21b348f7e5485fae740d845c65a880f5d1eda1e063bc59bef92d1f7d0c55"}, - {file = "rpds_py-0.17.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f175e95a197f6a4059b50757a3dca33b32b61691bdbd22c29e8a8d21d3914cae"}, - {file = "rpds_py-0.17.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1701fc54460ae2e5efc1dd6350eafd7a760f516df8dbe51d4a1c79d69472fbd4"}, - {file = "rpds_py-0.17.1-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:9051e3d2af8f55b42061603e29e744724cb5f65b128a491446cc029b3e2ea896"}, - {file = "rpds_py-0.17.1-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:7450dbd659fed6dd41d1a7d47ed767e893ba402af8ae664c157c255ec6067fde"}, - {file = "rpds_py-0.17.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:5a024fa96d541fd7edaa0e9d904601c6445e95a729a2900c5aec6555fe921ed6"}, - {file = "rpds_py-0.17.1-cp38-none-win32.whl", hash = "sha256:da1ead63368c04a9bded7904757dfcae01eba0e0f9bc41d3d7f57ebf1c04015a"}, - {file = "rpds_py-0.17.1-cp38-none-win_amd64.whl", hash = "sha256:841320e1841bb53fada91c9725e766bb25009cfd4144e92298db296fb6c894fb"}, - {file = "rpds_py-0.17.1-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:f6c43b6f97209e370124baf2bf40bb1e8edc25311a158867eb1c3a5d449ebc7a"}, - {file = "rpds_py-0.17.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:5e7d63ec01fe7c76c2dbb7e972fece45acbb8836e72682bde138e7e039906e2c"}, - {file = "rpds_py-0.17.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:81038ff87a4e04c22e1d81f947c6ac46f122e0c80460b9006e6517c4d842a6ec"}, - {file = "rpds_py-0.17.1-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:810685321f4a304b2b55577c915bece4c4a06dfe38f6e62d9cc1d6ca8ee86b99"}, - {file = "rpds_py-0.17.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:25f071737dae674ca8937a73d0f43f5a52e92c2d178330b4c0bb6ab05586ffa6"}, - {file = "rpds_py-0.17.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:aa5bfb13f1e89151ade0eb812f7b0d7a4d643406caaad65ce1cbabe0a66d695f"}, - {file = "rpds_py-0.17.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dfe07308b311a8293a0d5ef4e61411c5c20f682db6b5e73de6c7c8824272c256"}, - {file = "rpds_py-0.17.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a000133a90eea274a6f28adc3084643263b1e7c1a5a66eb0a0a7a36aa757ed74"}, - {file = "rpds_py-0.17.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:5d0e8a6434a3fbf77d11448c9c25b2f25244226cfbec1a5159947cac5b8c5fa4"}, - {file = "rpds_py-0.17.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:efa767c220d94aa4ac3a6dd3aeb986e9f229eaf5bce92d8b1b3018d06bed3772"}, - {file = "rpds_py-0.17.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:dbc56680ecf585a384fbd93cd42bc82668b77cb525343170a2d86dafaed2a84b"}, - {file = "rpds_py-0.17.1-cp39-none-win32.whl", hash = "sha256:270987bc22e7e5a962b1094953ae901395e8c1e1e83ad016c5cfcfff75a15a3f"}, - {file = "rpds_py-0.17.1-cp39-none-win_amd64.whl", hash = "sha256:2a7b2f2f56a16a6d62e55354dd329d929560442bd92e87397b7a9586a32e3e76"}, - {file = "rpds_py-0.17.1-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:a3264e3e858de4fc601741498215835ff324ff2482fd4e4af61b46512dd7fc83"}, - {file = "rpds_py-0.17.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:f2f3b28b40fddcb6c1f1f6c88c6f3769cd933fa493ceb79da45968a21dccc920"}, - {file = "rpds_py-0.17.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9584f8f52010295a4a417221861df9bea4c72d9632562b6e59b3c7b87a1522b7"}, - {file = "rpds_py-0.17.1-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c64602e8be701c6cfe42064b71c84ce62ce66ddc6422c15463fd8127db3d8066"}, - {file = "rpds_py-0.17.1-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:060f412230d5f19fc8c8b75f315931b408d8ebf56aec33ef4168d1b9e54200b1"}, - {file = "rpds_py-0.17.1-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b9412abdf0ba70faa6e2ee6c0cc62a8defb772e78860cef419865917d86c7342"}, - {file = "rpds_py-0.17.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9737bdaa0ad33d34c0efc718741abaafce62fadae72c8b251df9b0c823c63b22"}, - {file = "rpds_py-0.17.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9f0e4dc0f17dcea4ab9d13ac5c666b6b5337042b4d8f27e01b70fae41dd65c57"}, - {file = "rpds_py-0.17.1-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:1db228102ab9d1ff4c64148c96320d0be7044fa28bd865a9ce628ce98da5973d"}, - {file = "rpds_py-0.17.1-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:d8bbd8e56f3ba25a7d0cf980fc42b34028848a53a0e36c9918550e0280b9d0b6"}, - {file = "rpds_py-0.17.1-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:be22ae34d68544df293152b7e50895ba70d2a833ad9566932d750d3625918b82"}, - {file = "rpds_py-0.17.1-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:bf046179d011e6114daf12a534d874958b039342b347348a78b7cdf0dd9d6041"}, - {file = "rpds_py-0.17.1-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:1a746a6d49665058a5896000e8d9d2f1a6acba8a03b389c1e4c06e11e0b7f40d"}, - {file = "rpds_py-0.17.1-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f0b8bf5b8db49d8fd40f54772a1dcf262e8be0ad2ab0206b5a2ec109c176c0a4"}, - {file = "rpds_py-0.17.1-pp38-pypy38_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f7f4cb1f173385e8a39c29510dd11a78bf44e360fb75610594973f5ea141028b"}, - {file = "rpds_py-0.17.1-pp38-pypy38_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7fbd70cb8b54fe745301921b0816c08b6d917593429dfc437fd024b5ba713c58"}, - {file = "rpds_py-0.17.1-pp38-pypy38_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9bdf1303df671179eaf2cb41e8515a07fc78d9d00f111eadbe3e14262f59c3d0"}, - {file = "rpds_py-0.17.1-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fad059a4bd14c45776600d223ec194e77db6c20255578bb5bcdd7c18fd169361"}, - {file = "rpds_py-0.17.1-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:3664d126d3388a887db44c2e293f87d500c4184ec43d5d14d2d2babdb4c64cad"}, - {file = "rpds_py-0.17.1-pp38-pypy38_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:698ea95a60c8b16b58be9d854c9f993c639f5c214cf9ba782eca53a8789d6b19"}, - {file = "rpds_py-0.17.1-pp38-pypy38_pp73-musllinux_1_2_i686.whl", hash = "sha256:c3d2010656999b63e628a3c694f23020322b4178c450dc478558a2b6ef3cb9bb"}, - {file = "rpds_py-0.17.1-pp38-pypy38_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:938eab7323a736533f015e6069a7d53ef2dcc841e4e533b782c2bfb9fb12d84b"}, - {file = "rpds_py-0.17.1-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:1e626b365293a2142a62b9a614e1f8e331b28f3ca57b9f05ebbf4cf2a0f0bdc5"}, - {file = "rpds_py-0.17.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:380e0df2e9d5d5d339803cfc6d183a5442ad7ab3c63c2a0982e8c824566c5ccc"}, - {file = "rpds_py-0.17.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b760a56e080a826c2e5af09002c1a037382ed21d03134eb6294812dda268c811"}, - {file = "rpds_py-0.17.1-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5576ee2f3a309d2bb403ec292d5958ce03953b0e57a11d224c1f134feaf8c40f"}, - {file = "rpds_py-0.17.1-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1f3c3461ebb4c4f1bbc70b15d20b565759f97a5aaf13af811fcefc892e9197ba"}, - {file = "rpds_py-0.17.1-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:637b802f3f069a64436d432117a7e58fab414b4e27a7e81049817ae94de45d8d"}, - {file = "rpds_py-0.17.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ffee088ea9b593cc6160518ba9bd319b5475e5f3e578e4552d63818773c6f56a"}, - {file = "rpds_py-0.17.1-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:3ac732390d529d8469b831949c78085b034bff67f584559340008d0f6041a049"}, - {file = "rpds_py-0.17.1-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:93432e747fb07fa567ad9cc7aaadd6e29710e515aabf939dfbed8046041346c6"}, - {file = "rpds_py-0.17.1-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:7b7d9ca34542099b4e185b3c2a2b2eda2e318a7dbde0b0d83357a6d4421b5296"}, - {file = "rpds_py-0.17.1-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:0387ce69ba06e43df54e43968090f3626e231e4bc9150e4c3246947567695f68"}, - {file = "rpds_py-0.17.1.tar.gz", hash = "sha256:0210b2668f24c078307260bf88bdac9d6f1093635df5123789bfee4d8d7fc8e7"}, + {file = "rpds_py-0.18.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:5b4e7d8d6c9b2e8ee2d55c90b59c707ca59bc30058269b3db7b1f8df5763557e"}, + {file = "rpds_py-0.18.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c463ed05f9dfb9baebef68048aed8dcdc94411e4bf3d33a39ba97e271624f8f7"}, + {file = "rpds_py-0.18.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:01e36a39af54a30f28b73096dd39b6802eddd04c90dbe161c1b8dbe22353189f"}, + {file = "rpds_py-0.18.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d62dec4976954a23d7f91f2f4530852b0c7608116c257833922a896101336c51"}, + {file = "rpds_py-0.18.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dd18772815d5f008fa03d2b9a681ae38d5ae9f0e599f7dda233c439fcaa00d40"}, + {file = "rpds_py-0.18.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:923d39efa3cfb7279a0327e337a7958bff00cc447fd07a25cddb0a1cc9a6d2da"}, + {file = "rpds_py-0.18.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:39514da80f971362f9267c600b6d459bfbbc549cffc2cef8e47474fddc9b45b1"}, + {file = "rpds_py-0.18.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a34d557a42aa28bd5c48a023c570219ba2593bcbbb8dc1b98d8cf5d529ab1434"}, + {file = "rpds_py-0.18.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:93df1de2f7f7239dc9cc5a4a12408ee1598725036bd2dedadc14d94525192fc3"}, + {file = "rpds_py-0.18.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:34b18ba135c687f4dac449aa5157d36e2cbb7c03cbea4ddbd88604e076aa836e"}, + {file = "rpds_py-0.18.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:c0b5dcf9193625afd8ecc92312d6ed78781c46ecbf39af9ad4681fc9f464af88"}, + {file = "rpds_py-0.18.0-cp310-none-win32.whl", hash = "sha256:c4325ff0442a12113a6379af66978c3fe562f846763287ef66bdc1d57925d337"}, + {file = "rpds_py-0.18.0-cp310-none-win_amd64.whl", hash = "sha256:7223a2a5fe0d217e60a60cdae28d6949140dde9c3bcc714063c5b463065e3d66"}, + {file = "rpds_py-0.18.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:3a96e0c6a41dcdba3a0a581bbf6c44bb863f27c541547fb4b9711fd8cf0ffad4"}, + {file = "rpds_py-0.18.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:30f43887bbae0d49113cbaab729a112251a940e9b274536613097ab8b4899cf6"}, + {file = "rpds_py-0.18.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fcb25daa9219b4cf3a0ab24b0eb9a5cc8949ed4dc72acb8fa16b7e1681aa3c58"}, + {file = "rpds_py-0.18.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d68c93e381010662ab873fea609bf6c0f428b6d0bb00f2c6939782e0818d37bf"}, + {file = "rpds_py-0.18.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b34b7aa8b261c1dbf7720b5d6f01f38243e9b9daf7e6b8bc1fd4657000062f2c"}, + {file = "rpds_py-0.18.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2e6d75ab12b0bbab7215e5d40f1e5b738aa539598db27ef83b2ec46747df90e1"}, + {file = "rpds_py-0.18.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0b8612cd233543a3781bc659c731b9d607de65890085098986dfd573fc2befe5"}, + {file = "rpds_py-0.18.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:aec493917dd45e3c69d00a8874e7cbed844efd935595ef78a0f25f14312e33c6"}, + {file = "rpds_py-0.18.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:661d25cbffaf8cc42e971dd570d87cb29a665f49f4abe1f9e76be9a5182c4688"}, + {file = "rpds_py-0.18.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:1df3659d26f539ac74fb3b0c481cdf9d725386e3552c6fa2974f4d33d78e544b"}, + {file = "rpds_py-0.18.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a1ce3ba137ed54f83e56fb983a5859a27d43a40188ba798993812fed73c70836"}, + {file = "rpds_py-0.18.0-cp311-none-win32.whl", hash = "sha256:69e64831e22a6b377772e7fb337533c365085b31619005802a79242fee620bc1"}, + {file = "rpds_py-0.18.0-cp311-none-win_amd64.whl", hash = "sha256:998e33ad22dc7ec7e030b3df701c43630b5bc0d8fbc2267653577e3fec279afa"}, + {file = "rpds_py-0.18.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:7f2facbd386dd60cbbf1a794181e6aa0bd429bd78bfdf775436020172e2a23f0"}, + {file = "rpds_py-0.18.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1d9a5be316c15ffb2b3c405c4ff14448c36b4435be062a7f578ccd8b01f0c4d8"}, + {file = "rpds_py-0.18.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cd5bf1af8efe569654bbef5a3e0a56eca45f87cfcffab31dd8dde70da5982475"}, + {file = "rpds_py-0.18.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5417558f6887e9b6b65b4527232553c139b57ec42c64570569b155262ac0754f"}, + {file = "rpds_py-0.18.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:56a737287efecafc16f6d067c2ea0117abadcd078d58721f967952db329a3e5c"}, + {file = "rpds_py-0.18.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8f03bccbd8586e9dd37219bce4d4e0d3ab492e6b3b533e973fa08a112cb2ffc9"}, + {file = "rpds_py-0.18.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4457a94da0d5c53dc4b3e4de1158bdab077db23c53232f37a3cb7afdb053a4e3"}, + {file = "rpds_py-0.18.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:0ab39c1ba9023914297dd88ec3b3b3c3f33671baeb6acf82ad7ce883f6e8e157"}, + {file = "rpds_py-0.18.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:9d54553c1136b50fd12cc17e5b11ad07374c316df307e4cfd6441bea5fb68496"}, + {file = "rpds_py-0.18.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:0af039631b6de0397ab2ba16eaf2872e9f8fca391b44d3d8cac317860a700a3f"}, + {file = "rpds_py-0.18.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:84ffab12db93b5f6bad84c712c92060a2d321b35c3c9960b43d08d0f639d60d7"}, + {file = "rpds_py-0.18.0-cp312-none-win32.whl", hash = "sha256:685537e07897f173abcf67258bee3c05c374fa6fff89d4c7e42fb391b0605e98"}, + {file = "rpds_py-0.18.0-cp312-none-win_amd64.whl", hash = "sha256:e003b002ec72c8d5a3e3da2989c7d6065b47d9eaa70cd8808b5384fbb970f4ec"}, + {file = "rpds_py-0.18.0-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:08f9ad53c3f31dfb4baa00da22f1e862900f45908383c062c27628754af2e88e"}, + {file = "rpds_py-0.18.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:c0013fe6b46aa496a6749c77e00a3eb07952832ad6166bd481c74bda0dcb6d58"}, + {file = "rpds_py-0.18.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e32a92116d4f2a80b629778280103d2a510a5b3f6314ceccd6e38006b5e92dcb"}, + {file = "rpds_py-0.18.0-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e541ec6f2ec456934fd279a3120f856cd0aedd209fc3852eca563f81738f6861"}, + {file = "rpds_py-0.18.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bed88b9a458e354014d662d47e7a5baafd7ff81c780fd91584a10d6ec842cb73"}, + {file = "rpds_py-0.18.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2644e47de560eb7bd55c20fc59f6daa04682655c58d08185a9b95c1970fa1e07"}, + {file = "rpds_py-0.18.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8e8916ae4c720529e18afa0b879473049e95949bf97042e938530e072fde061d"}, + {file = "rpds_py-0.18.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:465a3eb5659338cf2a9243e50ad9b2296fa15061736d6e26240e713522b6235c"}, + {file = "rpds_py-0.18.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:ea7d4a99f3b38c37eac212dbd6ec42b7a5ec51e2c74b5d3223e43c811609e65f"}, + {file = "rpds_py-0.18.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:67071a6171e92b6da534b8ae326505f7c18022c6f19072a81dcf40db2638767c"}, + {file = "rpds_py-0.18.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:41ef53e7c58aa4ef281da975f62c258950f54b76ec8e45941e93a3d1d8580594"}, + {file = "rpds_py-0.18.0-cp38-none-win32.whl", hash = "sha256:fdea4952db2793c4ad0bdccd27c1d8fdd1423a92f04598bc39425bcc2b8ee46e"}, + {file = "rpds_py-0.18.0-cp38-none-win_amd64.whl", hash = "sha256:7cd863afe7336c62ec78d7d1349a2f34c007a3cc6c2369d667c65aeec412a5b1"}, + {file = "rpds_py-0.18.0-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:5307def11a35f5ae4581a0b658b0af8178c65c530e94893345bebf41cc139d33"}, + {file = "rpds_py-0.18.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:77f195baa60a54ef9d2de16fbbfd3ff8b04edc0c0140a761b56c267ac11aa467"}, + {file = "rpds_py-0.18.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:39f5441553f1c2aed4de4377178ad8ff8f9d733723d6c66d983d75341de265ab"}, + {file = "rpds_py-0.18.0-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9a00312dea9310d4cb7dbd7787e722d2e86a95c2db92fbd7d0155f97127bcb40"}, + {file = "rpds_py-0.18.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8f2fc11e8fe034ee3c34d316d0ad8808f45bc3b9ce5857ff29d513f3ff2923a1"}, + {file = "rpds_py-0.18.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:586f8204935b9ec884500498ccc91aa869fc652c40c093bd9e1471fbcc25c022"}, + {file = "rpds_py-0.18.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ddc2f4dfd396c7bfa18e6ce371cba60e4cf9d2e5cdb71376aa2da264605b60b9"}, + {file = "rpds_py-0.18.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5ddcba87675b6d509139d1b521e0c8250e967e63b5909a7e8f8944d0f90ff36f"}, + {file = "rpds_py-0.18.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:7bd339195d84439cbe5771546fe8a4e8a7a045417d8f9de9a368c434e42a721e"}, + {file = "rpds_py-0.18.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:d7c36232a90d4755b720fbd76739d8891732b18cf240a9c645d75f00639a9024"}, + {file = "rpds_py-0.18.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:6b0817e34942b2ca527b0e9298373e7cc75f429e8da2055607f4931fded23e20"}, + {file = "rpds_py-0.18.0-cp39-none-win32.whl", hash = "sha256:99f70b740dc04d09e6b2699b675874367885217a2e9f782bdf5395632ac663b7"}, + {file = "rpds_py-0.18.0-cp39-none-win_amd64.whl", hash = "sha256:6ef687afab047554a2d366e112dd187b62d261d49eb79b77e386f94644363294"}, + {file = "rpds_py-0.18.0-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:ad36cfb355e24f1bd37cac88c112cd7730873f20fb0bdaf8ba59eedf8216079f"}, + {file = "rpds_py-0.18.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:36b3ee798c58ace201289024b52788161e1ea133e4ac93fba7d49da5fec0ef9e"}, + {file = "rpds_py-0.18.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f8a2f084546cc59ea99fda8e070be2fd140c3092dc11524a71aa8f0f3d5a55ca"}, + {file = "rpds_py-0.18.0-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e4461d0f003a0aa9be2bdd1b798a041f177189c1a0f7619fe8c95ad08d9a45d7"}, + {file = "rpds_py-0.18.0-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8db715ebe3bb7d86d77ac1826f7d67ec11a70dbd2376b7cc214199360517b641"}, + {file = "rpds_py-0.18.0-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:793968759cd0d96cac1e367afd70c235867831983f876a53389ad869b043c948"}, + {file = "rpds_py-0.18.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:66e6a3af5a75363d2c9a48b07cb27c4ea542938b1a2e93b15a503cdfa8490795"}, + {file = "rpds_py-0.18.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6ef0befbb5d79cf32d0266f5cff01545602344eda89480e1dd88aca964260b18"}, + {file = "rpds_py-0.18.0-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:1d4acf42190d449d5e89654d5c1ed3a4f17925eec71f05e2a41414689cda02d1"}, + {file = "rpds_py-0.18.0-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:a5f446dd5055667aabaee78487f2b5ab72e244f9bc0b2ffebfeec79051679984"}, + {file = "rpds_py-0.18.0-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:9dbbeb27f4e70bfd9eec1be5477517365afe05a9b2c441a0b21929ee61048124"}, + {file = "rpds_py-0.18.0-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:22806714311a69fd0af9b35b7be97c18a0fc2826e6827dbb3a8c94eac6cf7eeb"}, + {file = "rpds_py-0.18.0-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:b34ae4636dfc4e76a438ab826a0d1eed2589ca7d9a1b2d5bb546978ac6485461"}, + {file = "rpds_py-0.18.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8c8370641f1a7f0e0669ddccca22f1da893cef7628396431eb445d46d893e5cd"}, + {file = "rpds_py-0.18.0-pp38-pypy38_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c8362467a0fdeccd47935f22c256bec5e6abe543bf0d66e3d3d57a8fb5731863"}, + {file = "rpds_py-0.18.0-pp38-pypy38_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:11a8c85ef4a07a7638180bf04fe189d12757c696eb41f310d2426895356dcf05"}, + {file = "rpds_py-0.18.0-pp38-pypy38_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b316144e85316da2723f9d8dc75bada12fa58489a527091fa1d5a612643d1a0e"}, + {file = "rpds_py-0.18.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cf1ea2e34868f6fbf070e1af291c8180480310173de0b0c43fc38a02929fc0e3"}, + {file = "rpds_py-0.18.0-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e546e768d08ad55b20b11dbb78a745151acbd938f8f00d0cfbabe8b0199b9880"}, + {file = "rpds_py-0.18.0-pp38-pypy38_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:4901165d170a5fde6f589acb90a6b33629ad1ec976d4529e769c6f3d885e3e80"}, + {file = "rpds_py-0.18.0-pp38-pypy38_pp73-musllinux_1_2_i686.whl", hash = "sha256:618a3d6cae6ef8ec88bb76dd80b83cfe415ad4f1d942ca2a903bf6b6ff97a2da"}, + {file = "rpds_py-0.18.0-pp38-pypy38_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:ed4eb745efbff0a8e9587d22a84be94a5eb7d2d99c02dacf7bd0911713ed14dd"}, + {file = "rpds_py-0.18.0-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:6c81e5f372cd0dc5dc4809553d34f832f60a46034a5f187756d9b90586c2c307"}, + {file = "rpds_py-0.18.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:43fbac5f22e25bee1d482c97474f930a353542855f05c1161fd804c9dc74a09d"}, + {file = "rpds_py-0.18.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6d7faa6f14017c0b1e69f5e2c357b998731ea75a442ab3841c0dbbbfe902d2c4"}, + {file = "rpds_py-0.18.0-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:08231ac30a842bd04daabc4d71fddd7e6d26189406d5a69535638e4dcb88fe76"}, + {file = "rpds_py-0.18.0-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:044a3e61a7c2dafacae99d1e722cc2d4c05280790ec5a05031b3876809d89a5c"}, + {file = "rpds_py-0.18.0-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3f26b5bd1079acdb0c7a5645e350fe54d16b17bfc5e71f371c449383d3342e17"}, + {file = "rpds_py-0.18.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:482103aed1dfe2f3b71a58eff35ba105289b8d862551ea576bd15479aba01f66"}, + {file = "rpds_py-0.18.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1374f4129f9bcca53a1bba0bb86bf78325a0374577cf7e9e4cd046b1e6f20e24"}, + {file = "rpds_py-0.18.0-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:635dc434ff724b178cb192c70016cc0ad25a275228f749ee0daf0eddbc8183b1"}, + {file = "rpds_py-0.18.0-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:bc362ee4e314870a70f4ae88772d72d877246537d9f8cb8f7eacf10884862432"}, + {file = "rpds_py-0.18.0-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:4832d7d380477521a8c1644bbab6588dfedea5e30a7d967b5fb75977c45fd77f"}, + {file = "rpds_py-0.18.0.tar.gz", hash = "sha256:42821446ee7a76f5d9f71f9e33a4fb2ffd724bb3e7f93386150b61a43115788d"}, ] [[package]] @@ -3642,4 +3658,4 @@ virustotal = ["validators"] [metadata] lock-version = "2.0" python-versions = "^3.8" -content-hash = "38686d7ffa7a8e3771b882acf0f42d145419456c7779e01c7c67dd639867d00f" +content-hash = "417ea88a301b1edb29d547abb4e1693dd97391db39118c2ed8f77478c471fc5e" diff --git a/pyproject.toml b/pyproject.toml index 16d11dd..982918b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "pymisp" -version = "2.4.184.3" +version = "2.4.185" description = "Python API for MISP." authors = ["Raphaël Vinot "] license = "BSD-2-Clause" @@ -82,7 +82,7 @@ ipython = [ {version = "^8.18.0", python = ">=3.9"}, {version = "^8.19.0", python = ">=3.10"} ] -jupyterlab = "^4.1.0" +jupyterlab = "^4.1.1" types-requests = "^2.31.0.20240125" types-python-dateutil = "^2.8.19.20240106" types-redis = "^4.6.0.20240106" From 492cfba2d2ad015d3fcda6e16c221fdefd93eca2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Vinot?= Date: Fri, 16 Feb 2024 14:47:55 +0100 Subject: [PATCH 78/80] chg: Bump changelog --- CHANGELOG.txt | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 6db3c45..67a609f 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -2,11 +2,20 @@ Changelog ========= +v2.4.185 (2024-02-16) +--------------------- + +Changes +~~~~~~~ +- Bump deps, version. [Raphaël Vinot] + + v2.4.184.3 (2024-02-12) ----------------------- Changes ~~~~~~~ +- Bump changelog. [Raphaël Vinot] - Bump version. [Raphaël Vinot] - Bump deps. [Raphaël Vinot] From 94ff206f67c6e0d847dfc666ed453c7e97e3e019 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Vinot?= Date: Thu, 22 Feb 2024 14:29:36 +0100 Subject: [PATCH 79/80] fix: Disable WL when calling the disable method, not toggle. Fix #1159 --- pymisp/api.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pymisp/api.py b/pymisp/api.py index ffbb08b..bc8e7cc 100644 --- a/pymisp/api.py +++ b/pymisp/api.py @@ -1292,12 +1292,12 @@ class PyMISP: w.from_dict(**wl) return w - def toggle_warninglist(self, warninglist_id: str | int | list[int] | None = None, warninglist_name: str | list[str] | None = None, force_enable: bool = False) -> dict[str, Any] | list[dict[str, Any]]: + def toggle_warninglist(self, warninglist_id: str | int | list[int] | None = None, warninglist_name: str | list[str] | None = None, force_enable: bool | None = None) -> dict[str, Any] | list[dict[str, Any]]: '''Toggle (enable/disable) the status of a warninglist by id: https://www.misp-project.org/openapi/#tag/Warninglists/operation/toggleEnableWarninglist :param warninglist_id: ID of the WarningList :param warninglist_name: name of the WarningList - :param force_enable: Force the warning list in the enabled state (does nothing if already enabled) + :param force_enable: Force the warning list in the enabled state (does nothing if already enabled) - None means toggle. ''' if warninglist_id is None and warninglist_name is None: raise PyMISPError('Either warninglist_id or warninglist_name is required.') @@ -1312,7 +1312,7 @@ class PyMISP: query['name'] = warninglist_name else: query['name'] = [warninglist_name] - if force_enable: + if force_enable is not None: query['enabled'] = force_enable response = self._prepare_request('POST', 'warninglists/toggleEnable', data=query) return self._check_json_response(response) From 313ad776c46856f32e87b6bc5cc918cfbf34f9bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Vinot?= Date: Thu, 22 Feb 2024 14:31:00 +0100 Subject: [PATCH 80/80] chg: Bump deps --- poetry.lock | 254 ++++++++++++++++++++++++------------------------- pyproject.toml | 6 +- 2 files changed, 130 insertions(+), 130 deletions(-) diff --git a/poetry.lock b/poetry.lock index 0da474d..794c49a 100644 --- a/poetry.lock +++ b/poetry.lock @@ -24,13 +24,13 @@ files = [ [[package]] name = "anyio" -version = "4.2.0" +version = "4.3.0" description = "High level compatibility layer for multiple asynchronous event loop implementations" optional = false python-versions = ">=3.8" files = [ - {file = "anyio-4.2.0-py3-none-any.whl", hash = "sha256:745843b39e829e108e518c489b31dc757de7d2131d53fac32bd8df268227bfee"}, - {file = "anyio-4.2.0.tar.gz", hash = "sha256:e1875bb4b4e2de1669f4bc7869b6d3f54231cdced71605e6e64c9be77e3be50f"}, + {file = "anyio-4.3.0-py3-none-any.whl", hash = "sha256:048e05d0f6caeed70d731f3db756d35dcc1f35747c8c403364a8332c630441b8"}, + {file = "anyio-4.3.0.tar.gz", hash = "sha256:f75253795a87df48568485fd18cdd2a3fa5c4f7c5be8e5e36637733fce06fed6"}, ] [package.dependencies] @@ -658,63 +658,63 @@ files = [ [[package]] name = "coverage" -version = "7.4.1" +version = "7.4.2" 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"}, + {file = "coverage-7.4.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:bf54c3e089179d9d23900e3efc86d46e4431188d9a657f345410eecdd0151f50"}, + {file = "coverage-7.4.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fe6e43c8b510719b48af7db9631b5fbac910ade4bd90e6378c85ac5ac706382c"}, + {file = "coverage-7.4.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8b98c89db1b150d851a7840142d60d01d07677a18f0f46836e691c38134ed18b"}, + {file = "coverage-7.4.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c5f9683be6a5b19cd776ee4e2f2ffb411424819c69afab6b2db3a0a364ec6642"}, + {file = "coverage-7.4.2-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:78cdcbf7b9cb83fe047ee09298e25b1cd1636824067166dc97ad0543b079d22f"}, + {file = "coverage-7.4.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:2599972b21911111114100d362aea9e70a88b258400672626efa2b9e2179609c"}, + {file = "coverage-7.4.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:ef00d31b7569ed3cb2036f26565f1984b9fc08541731ce01012b02a4c238bf03"}, + {file = "coverage-7.4.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:20a875bfd8c282985c4720c32aa05056f77a68e6d8bbc5fe8632c5860ee0b49b"}, + {file = "coverage-7.4.2-cp310-cp310-win32.whl", hash = "sha256:b3f2b1eb229f23c82898eedfc3296137cf1f16bb145ceab3edfd17cbde273fb7"}, + {file = "coverage-7.4.2-cp310-cp310-win_amd64.whl", hash = "sha256:7df95fdd1432a5d2675ce630fef5f239939e2b3610fe2f2b5bf21fa505256fa3"}, + {file = "coverage-7.4.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a8ddbd158e069dded57738ea69b9744525181e99974c899b39f75b2b29a624e2"}, + {file = "coverage-7.4.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:81a5fb41b0d24447a47543b749adc34d45a2cf77b48ca74e5bf3de60a7bd9edc"}, + {file = "coverage-7.4.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2412e98e70f16243be41d20836abd5f3f32edef07cbf8f407f1b6e1ceae783ac"}, + {file = "coverage-7.4.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ddb79414c15c6f03f56cc68fa06994f047cf20207c31b5dad3f6bab54a0f66ef"}, + {file = "coverage-7.4.2-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cf89ab85027427d351f1de918aff4b43f4eb5f33aff6835ed30322a86ac29c9e"}, + {file = "coverage-7.4.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:a178b7b1ac0f1530bb28d2e51f88c0bab3e5949835851a60dda80bff6052510c"}, + {file = "coverage-7.4.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:06fe398145a2e91edaf1ab4eee66149c6776c6b25b136f4a86fcbbb09512fd10"}, + {file = "coverage-7.4.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:18cac867950943fe93d6cd56a67eb7dcd2d4a781a40f4c1e25d6f1ed98721a55"}, + {file = "coverage-7.4.2-cp311-cp311-win32.whl", hash = "sha256:f72cdd2586f9a769570d4b5714a3837b3a59a53b096bb954f1811f6a0afad305"}, + {file = "coverage-7.4.2-cp311-cp311-win_amd64.whl", hash = "sha256:d779a48fac416387dd5673fc5b2d6bd903ed903faaa3247dc1865c65eaa5a93e"}, + {file = "coverage-7.4.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:adbdfcda2469d188d79771d5696dc54fab98a16d2ef7e0875013b5f56a251047"}, + {file = "coverage-7.4.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ac4bab32f396b03ebecfcf2971668da9275b3bb5f81b3b6ba96622f4ef3f6e17"}, + {file = "coverage-7.4.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:006d220ba2e1a45f1de083d5022d4955abb0aedd78904cd5a779b955b019ec73"}, + {file = "coverage-7.4.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3733545eb294e5ad274abe131d1e7e7de4ba17a144505c12feca48803fea5f64"}, + {file = "coverage-7.4.2-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:42a9e754aa250fe61f0f99986399cec086d7e7a01dd82fd863a20af34cbce962"}, + {file = "coverage-7.4.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:2ed37e16cf35c8d6e0b430254574b8edd242a367a1b1531bd1adc99c6a5e00fe"}, + {file = "coverage-7.4.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:b953275d4edfab6cc0ed7139fa773dfb89e81fee1569a932f6020ce7c6da0e8f"}, + {file = "coverage-7.4.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:32b4ab7e6c924f945cbae5392832e93e4ceb81483fd6dc4aa8fb1a97b9d3e0e1"}, + {file = "coverage-7.4.2-cp312-cp312-win32.whl", hash = "sha256:f5df76c58977bc35a49515b2fbba84a1d952ff0ec784a4070334dfbec28a2def"}, + {file = "coverage-7.4.2-cp312-cp312-win_amd64.whl", hash = "sha256:34423abbaad70fea9d0164add189eabaea679068ebdf693baa5c02d03e7db244"}, + {file = "coverage-7.4.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:5b11f9c6587668e495cc7365f85c93bed34c3a81f9f08b0920b87a89acc13469"}, + {file = "coverage-7.4.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:51593a1f05c39332f623d64d910445fdec3d2ac2d96b37ce7f331882d5678ddf"}, + {file = "coverage-7.4.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69f1665165ba2fe7614e2f0c1aed71e14d83510bf67e2ee13df467d1c08bf1e8"}, + {file = "coverage-7.4.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b3c8bbb95a699c80a167478478efe5e09ad31680931ec280bf2087905e3b95ec"}, + {file = "coverage-7.4.2-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:175f56572f25e1e1201d2b3e07b71ca4d201bf0b9cb8fad3f1dfae6a4188de86"}, + {file = "coverage-7.4.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:8562ca91e8c40864942615b1d0b12289d3e745e6b2da901d133f52f2d510a1e3"}, + {file = "coverage-7.4.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:d9a1ef0f173e1a19738f154fb3644f90d0ada56fe6c9b422f992b04266c55d5a"}, + {file = "coverage-7.4.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:f40ac873045db4fd98a6f40387d242bde2708a3f8167bd967ccd43ad46394ba2"}, + {file = "coverage-7.4.2-cp38-cp38-win32.whl", hash = "sha256:d1b750a8409bec61caa7824bfd64a8074b6d2d420433f64c161a8335796c7c6b"}, + {file = "coverage-7.4.2-cp38-cp38-win_amd64.whl", hash = "sha256:b4ae777bebaed89e3a7e80c4a03fac434a98a8abb5251b2a957d38fe3fd30088"}, + {file = "coverage-7.4.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3ff7f92ae5a456101ca8f48387fd3c56eb96353588e686286f50633a611afc95"}, + {file = "coverage-7.4.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:861d75402269ffda0b33af94694b8e0703563116b04c681b1832903fac8fd647"}, + {file = "coverage-7.4.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3507427d83fa961cbd73f11140f4a5ce84208d31756f7238d6257b2d3d868405"}, + {file = "coverage-7.4.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bf711d517e21fb5bc429f5c4308fbc430a8585ff2a43e88540264ae87871e36a"}, + {file = "coverage-7.4.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c00e54f0bd258ab25e7f731ca1d5144b0bf7bec0051abccd2bdcff65fa3262c9"}, + {file = "coverage-7.4.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:f8e845d894e39fb53834da826078f6dc1a933b32b1478cf437007367efaf6f6a"}, + {file = "coverage-7.4.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:840456cb1067dc350af9080298c7c2cfdddcedc1cb1e0b30dceecdaf7be1a2d3"}, + {file = "coverage-7.4.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:c11ca2df2206a4e3e4c4567f52594637392ed05d7c7fb73b4ea1c658ba560265"}, + {file = "coverage-7.4.2-cp39-cp39-win32.whl", hash = "sha256:3ff5bdb08d8938d336ce4088ca1a1e4b6c8cd3bef8bb3a4c0eb2f37406e49643"}, + {file = "coverage-7.4.2-cp39-cp39-win_amd64.whl", hash = "sha256:ac9e95cefcf044c98d4e2c829cd0669918585755dd9a92e28a1a7012322d0a95"}, + {file = "coverage-7.4.2-pp38.pp39.pp310-none-any.whl", hash = "sha256:f593a4a90118d99014517c2679e04a4ef5aee2d81aa05c26c734d271065efcb6"}, + {file = "coverage-7.4.2.tar.gz", hash = "sha256:1a5ee18e3a8d766075ce9314ed1cb695414bae67df6a4b0805f5137d93d6f1cb"}, ] [package.dependencies] @@ -725,43 +725,43 @@ toml = ["tomli"] [[package]] name = "cryptography" -version = "42.0.3" +version = "42.0.4" description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." optional = false python-versions = ">=3.7" files = [ - {file = "cryptography-42.0.3-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:de5086cd475d67113ccb6f9fae6d8fe3ac54a4f9238fd08bfdb07b03d791ff0a"}, - {file = "cryptography-42.0.3-cp37-abi3-macosx_10_12_x86_64.whl", hash = "sha256:935cca25d35dda9e7bd46a24831dfd255307c55a07ff38fd1a92119cffc34857"}, - {file = "cryptography-42.0.3-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:20100c22b298c9eaebe4f0b9032ea97186ac2555f426c3e70670f2517989543b"}, - {file = "cryptography-42.0.3-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2eb6368d5327d6455f20327fb6159b97538820355ec00f8cc9464d617caecead"}, - {file = "cryptography-42.0.3-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:39d5c93e95bcbc4c06313fc6a500cee414ee39b616b55320c1904760ad686938"}, - {file = "cryptography-42.0.3-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:3d96ea47ce6d0055d5b97e761d37b4e84195485cb5a38401be341fabf23bc32a"}, - {file = "cryptography-42.0.3-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:d1998e545081da0ab276bcb4b33cce85f775adb86a516e8f55b3dac87f469548"}, - {file = "cryptography-42.0.3-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:93fbee08c48e63d5d1b39ab56fd3fdd02e6c2431c3da0f4edaf54954744c718f"}, - {file = "cryptography-42.0.3-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:90147dad8c22d64b2ff7331f8d4cddfdc3ee93e4879796f837bdbb2a0b141e0c"}, - {file = "cryptography-42.0.3-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:4dcab7c25e48fc09a73c3e463d09ac902a932a0f8d0c568238b3696d06bf377b"}, - {file = "cryptography-42.0.3-cp37-abi3-win32.whl", hash = "sha256:1e935c2900fb53d31f491c0de04f41110351377be19d83d908c1fd502ae8daa5"}, - {file = "cryptography-42.0.3-cp37-abi3-win_amd64.whl", hash = "sha256:762f3771ae40e111d78d77cbe9c1035e886ac04a234d3ee0856bf4ecb3749d54"}, - {file = "cryptography-42.0.3-cp39-abi3-macosx_10_12_universal2.whl", hash = "sha256:0d3ec384058b642f7fb7e7bff9664030011ed1af8f852540c76a1317a9dd0d20"}, - {file = "cryptography-42.0.3-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:35772a6cffd1f59b85cb670f12faba05513446f80352fe811689b4e439b5d89e"}, - {file = "cryptography-42.0.3-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:04859aa7f12c2b5f7e22d25198ddd537391f1695df7057c8700f71f26f47a129"}, - {file = "cryptography-42.0.3-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:c3d1f5a1d403a8e640fa0887e9f7087331abb3f33b0f2207d2cc7f213e4a864c"}, - {file = "cryptography-42.0.3-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:df34312149b495d9d03492ce97471234fd9037aa5ba217c2a6ea890e9166f151"}, - {file = "cryptography-42.0.3-cp39-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:de4ae486041878dc46e571a4c70ba337ed5233a1344c14a0790c4c4be4bbb8b4"}, - {file = "cryptography-42.0.3-cp39-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:0fab2a5c479b360e5e0ea9f654bcebb535e3aa1e493a715b13244f4e07ea8eec"}, - {file = "cryptography-42.0.3-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:25b09b73db78facdfd7dd0fa77a3f19e94896197c86e9f6dc16bce7b37a96504"}, - {file = "cryptography-42.0.3-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:d5cf11bc7f0b71fb71af26af396c83dfd3f6eed56d4b6ef95d57867bf1e4ba65"}, - {file = "cryptography-42.0.3-cp39-abi3-win32.whl", hash = "sha256:0fea01527d4fb22ffe38cd98951c9044400f6eff4788cf52ae116e27d30a1ba3"}, - {file = "cryptography-42.0.3-cp39-abi3-win_amd64.whl", hash = "sha256:2619487f37da18d6826e27854a7f9d4d013c51eafb066c80d09c63cf24505306"}, - {file = "cryptography-42.0.3-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:ead69ba488f806fe1b1b4050febafdbf206b81fa476126f3e16110c818bac396"}, - {file = "cryptography-42.0.3-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:20180da1b508f4aefc101cebc14c57043a02b355d1a652b6e8e537967f1e1b46"}, - {file = "cryptography-42.0.3-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:5fbf0f3f0fac7c089308bd771d2c6c7b7d53ae909dce1db52d8e921f6c19bb3a"}, - {file = "cryptography-42.0.3-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:c23f03cfd7d9826cdcbad7850de67e18b4654179e01fe9bc623d37c2638eb4ef"}, - {file = "cryptography-42.0.3-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:db0480ffbfb1193ac4e1e88239f31314fe4c6cdcf9c0b8712b55414afbf80db4"}, - {file = "cryptography-42.0.3-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:6c25e1e9c2ce682d01fc5e2dde6598f7313027343bd14f4049b82ad0402e52cd"}, - {file = "cryptography-42.0.3-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:9541c69c62d7446539f2c1c06d7046aef822940d248fa4b8962ff0302862cc1f"}, - {file = "cryptography-42.0.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:1b797099d221df7cce5ff2a1d272761d1554ddf9a987d3e11f6459b38cd300fd"}, - {file = "cryptography-42.0.3.tar.gz", hash = "sha256:069d2ce9be5526a44093a0991c450fe9906cdf069e0e7cd67d9dee49a62b9ebe"}, + {file = "cryptography-42.0.4-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:ffc73996c4fca3d2b6c1c8c12bfd3ad00def8621da24f547626bf06441400449"}, + {file = "cryptography-42.0.4-cp37-abi3-macosx_10_12_x86_64.whl", hash = "sha256:db4b65b02f59035037fde0998974d84244a64c3265bdef32a827ab9b63d61b18"}, + {file = "cryptography-42.0.4-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dad9c385ba8ee025bb0d856714f71d7840020fe176ae0229de618f14dae7a6e2"}, + {file = "cryptography-42.0.4-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:69b22ab6506a3fe483d67d1ed878e1602bdd5912a134e6202c1ec672233241c1"}, + {file = "cryptography-42.0.4-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:e09469a2cec88fb7b078e16d4adec594414397e8879a4341c6ace96013463d5b"}, + {file = "cryptography-42.0.4-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:3e970a2119507d0b104f0a8e281521ad28fc26f2820687b3436b8c9a5fcf20d1"}, + {file = "cryptography-42.0.4-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:e53dc41cda40b248ebc40b83b31516487f7db95ab8ceac1f042626bc43a2f992"}, + {file = "cryptography-42.0.4-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:c3a5cbc620e1e17009f30dd34cb0d85c987afd21c41a74352d1719be33380885"}, + {file = "cryptography-42.0.4-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:6bfadd884e7280df24d26f2186e4e07556a05d37393b0f220a840b083dc6a824"}, + {file = "cryptography-42.0.4-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:01911714117642a3f1792c7f376db572aadadbafcd8d75bb527166009c9f1d1b"}, + {file = "cryptography-42.0.4-cp37-abi3-win32.whl", hash = "sha256:fb0cef872d8193e487fc6bdb08559c3aa41b659a7d9be48b2e10747f47863925"}, + {file = "cryptography-42.0.4-cp37-abi3-win_amd64.whl", hash = "sha256:c1f25b252d2c87088abc8bbc4f1ecbf7c919e05508a7e8628e6875c40bc70923"}, + {file = "cryptography-42.0.4-cp39-abi3-macosx_10_12_universal2.whl", hash = "sha256:15a1fb843c48b4a604663fa30af60818cd28f895572386e5f9b8a665874c26e7"}, + {file = "cryptography-42.0.4-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a1327f280c824ff7885bdeef8578f74690e9079267c1c8bd7dc5cc5aa065ae52"}, + {file = "cryptography-42.0.4-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6ffb03d419edcab93b4b19c22ee80c007fb2d708429cecebf1dd3258956a563a"}, + {file = "cryptography-42.0.4-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:1df6fcbf60560d2113b5ed90f072dc0b108d64750d4cbd46a21ec882c7aefce9"}, + {file = "cryptography-42.0.4-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:44a64043f743485925d3bcac548d05df0f9bb445c5fcca6681889c7c3ab12764"}, + {file = "cryptography-42.0.4-cp39-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:3c6048f217533d89f2f8f4f0fe3044bf0b2090453b7b73d0b77db47b80af8dff"}, + {file = "cryptography-42.0.4-cp39-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:6d0fbe73728c44ca3a241eff9aefe6496ab2656d6e7a4ea2459865f2e8613257"}, + {file = "cryptography-42.0.4-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:887623fe0d70f48ab3f5e4dbf234986b1329a64c066d719432d0698522749929"}, + {file = "cryptography-42.0.4-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:ce8613beaffc7c14f091497346ef117c1798c202b01153a8cc7b8e2ebaaf41c0"}, + {file = "cryptography-42.0.4-cp39-abi3-win32.whl", hash = "sha256:810bcf151caefc03e51a3d61e53335cd5c7316c0a105cc695f0959f2c638b129"}, + {file = "cryptography-42.0.4-cp39-abi3-win_amd64.whl", hash = "sha256:a0298bdc6e98ca21382afe914c642620370ce0470a01e1bef6dd9b5354c36854"}, + {file = "cryptography-42.0.4-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:5f8907fcf57392cd917892ae83708761c6ff3c37a8e835d7246ff0ad251d9298"}, + {file = "cryptography-42.0.4-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:12d341bd42cdb7d4937b0cabbdf2a94f949413ac4504904d0cdbdce4a22cbf88"}, + {file = "cryptography-42.0.4-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:1cdcdbd117681c88d717437ada72bdd5be9de117f96e3f4d50dab3f59fd9ab20"}, + {file = "cryptography-42.0.4-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:0e89f7b84f421c56e7ff69f11c441ebda73b8a8e6488d322ef71746224c20fce"}, + {file = "cryptography-42.0.4-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:f1e85a178384bf19e36779d91ff35c7617c885da487d689b05c1366f9933ad74"}, + {file = "cryptography-42.0.4-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:d2a27aca5597c8a71abbe10209184e1a8e91c1fd470b5070a2ea60cafec35bcd"}, + {file = "cryptography-42.0.4-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:4e36685cb634af55e0677d435d425043967ac2f3790ec652b2b88ad03b85c27b"}, + {file = "cryptography-42.0.4-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:f47be41843200f7faec0683ad751e5ef11b9a56a220d57f300376cd8aba81660"}, + {file = "cryptography-42.0.4.tar.gz", hash = "sha256:831a4b37accef30cccd34fcb916a5d7b5be3cbbe27268a02832c3e450aea39cb"}, ] [package.dependencies] @@ -972,13 +972,13 @@ files = [ [[package]] name = "httpcore" -version = "1.0.3" +version = "1.0.4" description = "A minimal low-level HTTP client." optional = false python-versions = ">=3.8" files = [ - {file = "httpcore-1.0.3-py3-none-any.whl", hash = "sha256:9a6a501c3099307d9fd76ac244e08503427679b1e81ceb1d922485e2f2462ad2"}, - {file = "httpcore-1.0.3.tar.gz", hash = "sha256:5c0f9546ad17dac4d0772b0808856eb616eb8b48ce94f49ed819fd6982a8a544"}, + {file = "httpcore-1.0.4-py3-none-any.whl", hash = "sha256:ac418c1db41bade2ad53ae2f3834a3a0f5ae76b56cf5aa497d2d033384fc7d73"}, + {file = "httpcore-1.0.4.tar.gz", hash = "sha256:cb2839ccfcba0d2d3c1131d3c3e26dfc327326fbe7a5dc0dbfe9f6c9151bb022"}, ] [package.dependencies] @@ -989,17 +989,17 @@ h11 = ">=0.13,<0.15" asyncio = ["anyio (>=4.0,<5.0)"] http2 = ["h2 (>=3,<5)"] socks = ["socksio (==1.*)"] -trio = ["trio (>=0.22.0,<0.24.0)"] +trio = ["trio (>=0.22.0,<0.25.0)"] [[package]] name = "httpx" -version = "0.26.0" +version = "0.27.0" description = "The next generation HTTP client." optional = false python-versions = ">=3.8" files = [ - {file = "httpx-0.26.0-py3-none-any.whl", hash = "sha256:8915f5a3627c4d47b73e8202457cb28f1266982d1159bd5779d86a80c0eab1cd"}, - {file = "httpx-0.26.0.tar.gz", hash = "sha256:451b55c30d5185ea6b23c2c793abf9bb237d2a7dfb901ced6ff69ad37ec1dfaf"}, + {file = "httpx-0.27.0-py3-none-any.whl", hash = "sha256:71d5465162c13681bff01ad59b2cc68dd838ea1f10e51574bac27103f00c91a5"}, + {file = "httpx-0.27.0.tar.gz", hash = "sha256:a0cb88a46f32dc874e04ee956e4c2764aba2aa228f650b06788ba6bda2962ab5"}, ] [package.dependencies] @@ -1196,13 +1196,13 @@ test-extra = ["curio", "matplotlib (!=3.2.0)", "nbformat", "numpy (>=1.22)", "pa [[package]] name = "ipython" -version = "8.21.0" +version = "8.22.0" description = "IPython: Productive Interactive Computing" optional = false python-versions = ">=3.10" files = [ - {file = "ipython-8.21.0-py3-none-any.whl", hash = "sha256:1050a3ab8473488d7eee163796b02e511d0735cf43a04ba2a8348bd0f2eaf8a5"}, - {file = "ipython-8.21.0.tar.gz", hash = "sha256:48fbc236fbe0e138b88773fa0437751f14c3645fb483f1d4c5dee58b37e5ce73"}, + {file = "ipython-8.22.0-py3-none-any.whl", hash = "sha256:a3e962e1d42927f5825dab048f4de617f5856cf3272fff1cb9245bea0c785a46"}, + {file = "ipython-8.22.0.tar.gz", hash = "sha256:bc649987e35a75ecccab7a245d7403710e3a289384c268d6d846ab8933ca0811"}, ] [package.dependencies] @@ -1211,16 +1211,16 @@ decorator = "*" exceptiongroup = {version = "*", markers = "python_version < \"3.11\""} jedi = ">=0.16" matplotlib-inline = "*" -pexpect = {version = ">4.3", markers = "sys_platform != \"win32\""} +pexpect = {version = ">4.3", markers = "sys_platform != \"win32\" and sys_platform != \"emscripten\""} prompt-toolkit = ">=3.0.41,<3.1.0" pygments = ">=2.4.0" stack-data = "*" traitlets = ">=5" [package.extras] -all = ["black", "curio", "docrepr", "exceptiongroup", "ipykernel", "ipyparallel", "ipywidgets", "matplotlib", "matplotlib (!=3.2.0)", "nbconvert", "nbformat", "notebook", "numpy (>=1.23)", "pandas", "pickleshare", "pytest (<8)", "pytest-asyncio (<0.22)", "qtconsole", "setuptools (>=18.5)", "sphinx (>=1.3)", "sphinx-rtd-theme", "stack-data", "testpath", "trio", "typing-extensions"] +all = ["ipython[black,doc,kernel,nbconvert,nbformat,notebook,parallel,qtconsole,terminal]", "ipython[test,test-extra]"] black = ["black"] -doc = ["docrepr", "exceptiongroup", "ipykernel", "matplotlib", "pickleshare", "pytest (<8)", "pytest-asyncio (<0.22)", "setuptools (>=18.5)", "sphinx (>=1.3)", "sphinx-rtd-theme", "stack-data", "testpath", "typing-extensions"] +doc = ["docrepr", "exceptiongroup", "ipykernel", "ipython[test]", "matplotlib", "setuptools (>=18.5)", "sphinx (>=1.3)", "sphinx-rtd-theme", "sphinxcontrib-jquery", "stack-data", "typing-extensions"] kernel = ["ipykernel"] nbconvert = ["nbconvert"] nbformat = ["nbformat"] @@ -1228,7 +1228,7 @@ notebook = ["ipywidgets", "notebook"] parallel = ["ipyparallel"] qtconsole = ["qtconsole"] test = ["pickleshare", "pytest (<8)", "pytest-asyncio (<0.22)", "testpath"] -test-extra = ["curio", "matplotlib (!=3.2.0)", "nbformat", "numpy (>=1.23)", "pandas", "pickleshare", "pytest (<8)", "pytest-asyncio (<0.22)", "testpath", "trio"] +test-extra = ["curio", "ipython[test]", "matplotlib (!=3.2.0)", "nbformat", "numpy (>=1.23)", "pandas", "trio"] [[package]] name = "isoduration" @@ -1282,13 +1282,13 @@ i18n = ["Babel (>=2.7)"] [[package]] name = "json5" -version = "0.9.14" +version = "0.9.17" description = "A Python implementation of the JSON5 data format." optional = false -python-versions = "*" +python-versions = ">=3.8" files = [ - {file = "json5-0.9.14-py2.py3-none-any.whl", hash = "sha256:740c7f1b9e584a468dbb2939d8d458db3427f2c93ae2139d05f47e453eae964f"}, - {file = "json5-0.9.14.tar.gz", hash = "sha256:9ed66c3a6ca3510a976a9ef9b8c0787de24802724ab1860bc0153c7fdd589b02"}, + {file = "json5-0.9.17-py2.py3-none-any.whl", hash = "sha256:f8ec1ecf985951d70f780f6f877c4baca6a47b6e61e02c4cd190138d10a7805a"}, + {file = "json5-0.9.17.tar.gz", hash = "sha256:717d99d657fa71b7094877b1d921b1cce40ab444389f6d770302563bb7dfd9ae"}, ] [package.extras] @@ -1491,13 +1491,13 @@ test = ["jupyter-server (>=2.0.0)", "pytest (>=7.0)", "pytest-jupyter[server] (> [[package]] name = "jupyterlab" -version = "4.1.1" +version = "4.1.2" description = "JupyterLab computational environment" optional = false python-versions = ">=3.8" files = [ - {file = "jupyterlab-4.1.1-py3-none-any.whl", hash = "sha256:fa3e8c18b804eac04e51ceebd9dd3dd396e08106816f0d09cc426799d7087632"}, - {file = "jupyterlab-4.1.1.tar.gz", hash = "sha256:8acc9f561729d8f32c14c294c397917cddfeeb13a5d46f811979b71b4911a9fd"}, + {file = "jupyterlab-4.1.2-py3-none-any.whl", hash = "sha256:aa88193f03cf4d3555f6712f04d74112b5eb85edd7d222c588c7603a26d33c5b"}, + {file = "jupyterlab-4.1.2.tar.gz", hash = "sha256:5d6348b3ed4085181499f621b7dfb6eb0b1f57f3586857aadfc8e3bf4c4885f9"}, ] [package.dependencies] @@ -1807,13 +1807,13 @@ test = ["flaky", "ipykernel (>=6.19.3)", "ipython", "ipywidgets", "nbconvert (>= [[package]] name = "nbconvert" -version = "7.16.0" -description = "Converting Jupyter Notebooks" +version = "7.16.1" +description = "Converting Jupyter Notebooks (.ipynb files) to other formats. Output formats include asciidoc, html, latex, markdown, pdf, py, rst, script. nbconvert can be used both as a Python library (`import nbconvert`) or as a command line tool (invoked as `jupyter nbconvert ...`)." optional = false python-versions = ">=3.8" files = [ - {file = "nbconvert-7.16.0-py3-none-any.whl", hash = "sha256:ad3dc865ea6e2768d31b7eb6c7ab3be014927216a5ece3ef276748dd809054c7"}, - {file = "nbconvert-7.16.0.tar.gz", hash = "sha256:813e6553796362489ae572e39ba1bff978536192fb518e10826b0e8cadf03ec8"}, + {file = "nbconvert-7.16.1-py3-none-any.whl", hash = "sha256:3188727dffadfdc9c6a1c7250729063d7bc78b355ad7aa023138afa030d1cd07"}, + {file = "nbconvert-7.16.1.tar.gz", hash = "sha256:e79e6a074f49ba3ed29428ed86487bf51509d9aab613bd8522ac08f6d28fd7fd"}, ] [package.dependencies] @@ -2312,13 +2312,13 @@ files = [ [[package]] name = "pytest" -version = "8.0.0" +version = "8.0.1" description = "pytest: simple powerful testing with Python" optional = false python-versions = ">=3.8" files = [ - {file = "pytest-8.0.0-py3-none-any.whl", hash = "sha256:50fb9cbe836c3f20f0dfa99c565201fb75dc54c8d76373cd1bde06b06657bdb6"}, - {file = "pytest-8.0.0.tar.gz", hash = "sha256:249b1b0864530ba251b7438274c4d251c58d868edaaec8762893ad4a0d71c36c"}, + {file = "pytest-8.0.1-py3-none-any.whl", hash = "sha256:3e4f16fe1c0a9dc9d9389161c127c3edc5d810c38d6793042fb81d9f48a59fca"}, + {file = "pytest-8.0.1.tar.gz", hash = "sha256:267f6563751877d772019b13aacbe4e860d73fe8f651f28112e9ac37de7513ae"}, ] [package.dependencies] @@ -3353,13 +3353,13 @@ files = [ [[package]] name = "types-redis" -version = "4.6.0.20240106" +version = "4.6.0.20240218" description = "Typing stubs for redis" optional = false python-versions = ">=3.8" files = [ - {file = "types-redis-4.6.0.20240106.tar.gz", hash = "sha256:2b2fa3a78f84559616242d23f86de5f4130dfd6c3b83fb2d8ce3329e503f756e"}, - {file = "types_redis-4.6.0.20240106-py3-none-any.whl", hash = "sha256:912de6507b631934bd225cdac310b04a58def94391003ba83939e5a10e99568d"}, + {file = "types-redis-4.6.0.20240218.tar.gz", hash = "sha256:5103d7e690e5c74c974a161317b2d59ac2303cf8bef24175b04c2a4c3486cb39"}, + {file = "types_redis-4.6.0.20240218-py3-none-any.whl", hash = "sha256:dc9c45a068240e33a04302aec5655cf41e80f91eecffccbb2df215b2f6fc375d"}, ] [package.dependencies] @@ -3368,13 +3368,13 @@ types-pyOpenSSL = "*" [[package]] name = "types-requests" -version = "2.31.0.20240125" +version = "2.31.0.20240218" description = "Typing stubs for requests" optional = false python-versions = ">=3.8" files = [ - {file = "types-requests-2.31.0.20240125.tar.gz", hash = "sha256:03a28ce1d7cd54199148e043b2079cdded22d6795d19a2c2a6791a4b2b5e2eb5"}, - {file = "types_requests-2.31.0.20240125-py3-none-any.whl", hash = "sha256:9592a9a4cb92d6d75d9b491a41477272b710e021011a2a3061157e2fb1f1a5d1"}, + {file = "types-requests-2.31.0.20240218.tar.gz", hash = "sha256:f1721dba8385958f504a5386240b92de4734e047a08a40751c1654d1ac3349c5"}, + {file = "types_requests-2.31.0.20240218-py3-none-any.whl", hash = "sha256:a82807ec6ddce8f00fe0e949da6d6bc1fbf1715420218a9640d695f70a9e5a9b"}, ] [package.dependencies] @@ -3447,13 +3447,13 @@ dev = ["flake8", "flake8-annotations", "flake8-bandit", "flake8-bugbear", "flake [[package]] name = "urllib3" -version = "2.2.0" +version = "2.2.1" 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"}, + {file = "urllib3-2.2.1-py3-none-any.whl", hash = "sha256:450b20ec296a467077128bff42b73080516e71b56ff59a60a02bef2232c4fa9d"}, + {file = "urllib3-2.2.1.tar.gz", hash = "sha256:d0570876c61ab9e520d776c38acbbb5b05a776d3f9ff98a5c8fd5162a444cf19"}, ] [package.dependencies] @@ -3658,4 +3658,4 @@ virustotal = ["validators"] [metadata] lock-version = "2.0" python-versions = "^3.8" -content-hash = "417ea88a301b1edb29d547abb4e1693dd97391db39118c2ed8f77478c471fc5e" +content-hash = "87ffab7b554e19ae1d029620c6861210b226f577aff26bdc436bc7c70230fd0e" diff --git a/pyproject.toml b/pyproject.toml index 982918b..0b8a208 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -82,10 +82,10 @@ ipython = [ {version = "^8.18.0", python = ">=3.9"}, {version = "^8.19.0", python = ">=3.10"} ] -jupyterlab = "^4.1.1" -types-requests = "^2.31.0.20240125" +jupyterlab = "^4.1.2" +types-requests = "^2.31.0.20240218" types-python-dateutil = "^2.8.19.20240106" -types-redis = "^4.6.0.20240106" +types-redis = "^4.6.0.20240218" types-Flask = "^1.1.6" pytest-cov = "^4.1.0"