From 253f1266352c56a8496a128b37d84a3ab70c90f2 Mon Sep 17 00:00:00 2001 From: vladimirgubarik Date: Tue, 6 May 2025 19:09:15 +0300 Subject: [PATCH 1/3] feature: user_joined_to_chat event support, typing fixes, version bump --- poetry.lock | 171 ++++++++---------- pybotx/bot/handler.py | 2 + pybotx/bot/handler_collector.py | 9 + pybotx/models/commands.py | 6 + pybotx/models/enums.py | 1 + .../system_events/user_joined_to_chat.py | 94 ++++++++++ pyproject.toml | 3 +- setup.cfg | 2 +- tests/system_events/factories.py | 66 +++++++ tests/system_events/test_join_to_chat.py | 68 +++++++ 10 files changed, 322 insertions(+), 100 deletions(-) create mode 100644 pybotx/models/system_events/user_joined_to_chat.py create mode 100644 tests/system_events/factories.py create mode 100644 tests/system_events/test_join_to_chat.py diff --git a/poetry.lock b/poetry.lock index 46dae4f7..c8159139 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 2.1.2 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.8.5 and should not be changed by hand. [[package]] name = "add-trailing-comma" @@ -6,7 +6,6 @@ version = "2.2.1" description = "Automatically add trailing commas to calls and literals" optional = false python-versions = ">=3.6.1" -groups = ["dev"] files = [ {file = "add_trailing_comma-2.2.1-py2.py3-none-any.whl", hash = "sha256:981c18282b38ec5bceab80ef11485440334d2a274fcf3fce1f91692374b6d818"}, {file = "add_trailing_comma-2.2.1.tar.gz", hash = "sha256:1640e97c4e85132633a6cb19b29e392dbaf9516292388afa685f7ef1012468e0"}, @@ -21,7 +20,6 @@ version = "1.2.5" description = "Asynchronous CSV reading/writing" optional = false python-versions = ">=3.6, <4" -groups = ["main"] files = [ {file = "aiocsv-1.2.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a8221a24220c3dfed5df80c87bb1e15d4863816954b5f1fca1dcfc14328c0131"}, {file = "aiocsv-1.2.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:274df72bc8d0d11060c148523203f93cfa830dc9901a053d27032e4be0acb50e"}, @@ -56,7 +54,6 @@ version = "23.2.1" description = "File support for asyncio." optional = false python-versions = ">=3.7" -groups = ["main"] files = [ {file = "aiofiles-23.2.1-py3-none-any.whl", hash = "sha256:19297512c647d4b27a2cf7c34caa7e405c0d60b5560618a29a9fe027b18b0107"}, {file = "aiofiles-23.2.1.tar.gz", hash = "sha256:84ec2218d8419404abcb9f0c02df3f34c6e0a68ed41072acfb1cef5cbc29051a"}, @@ -68,7 +65,6 @@ version = "4.4.0" description = "High level compatibility layer for multiple asynchronous event loop implementations" optional = false python-versions = ">=3.8" -groups = ["main", "dev"] files = [ {file = "anyio-4.4.0-py3-none-any.whl", hash = "sha256:c1b2d8f46a8a812513012e1107cb0e68c17159a7a594208005a57dc776e1bdc7"}, {file = "anyio-4.4.0.tar.gz", hash = "sha256:5aadc6a1bbb7cdb0bede386cac5e2940f5e2ff3aa20277e991cf028e0585ce94"}, @@ -82,7 +78,7 @@ 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"] -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) ; platform_python_implementation == \"CPython\" and platform_system != \"Windows\""] +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]] @@ -91,7 +87,6 @@ version = "3.8.1" description = "ASGI specs, helper code, and adapters" optional = false python-versions = ">=3.8" -groups = ["dev"] files = [ {file = "asgiref-3.8.1-py3-none-any.whl", hash = "sha256:3e1e3ecc849832fe52ccf2cb6686b7a55f82bb1d6aee72a58826471390335e47"}, {file = "asgiref-3.8.1.tar.gz", hash = "sha256:c343bd80a0bec947a9860adb4c432ffa7db769836c64238fc34bdc3fec84d590"}, @@ -109,7 +104,6 @@ version = "0.8.1" description = "Read/rewrite/write Python ASTs" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,>=2.7" -groups = ["dev"] files = [ {file = "astor-0.8.1-py2.py3-none-any.whl", hash = "sha256:070a54e890cefb5b3739d19f30f5a5ec840ffc9c50ffa7d23cc9fc1a38ebbfc5"}, {file = "astor-0.8.1.tar.gz", hash = "sha256:6a6effda93f4e1ce9f618779b2dd1d9d84f1e32812c23a29b3fff6fd7f63fa5e"}, @@ -121,7 +115,6 @@ version = "23.2.0" description = "Classes Without Boilerplate" optional = false python-versions = ">=3.7" -groups = ["dev"] files = [ {file = "attrs-23.2.0-py3-none-any.whl", hash = "sha256:99b87a485a5820b23b879f04c2305b44b951b502fd64be915879d77a7e8fc6f1"}, {file = "attrs-23.2.0.tar.gz", hash = "sha256:935dc3b529c262f6cf76e50877d35a4bd3c1de194fd41f47a2b7ae8f19971f30"}, @@ -132,8 +125,8 @@ cov = ["attrs[tests]", "coverage[toml] (>=5.3)"] 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-mypy = ["mypy (>=1.6) ; platform_python_implementation == \"CPython\" and python_version >= \"3.8\"", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.8\""] -tests-no-zope = ["attrs[tests-mypy]", "cloudpickle ; platform_python_implementation == \"CPython\"", "hypothesis", "pympler", "pytest (>=4.3.0)", "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 = "autoflake" @@ -141,7 +134,6 @@ version = "1.7.8" description = "Removes unused imports and unused variables" optional = false python-versions = ">=3.7" -groups = ["dev"] files = [ {file = "autoflake-1.7.8-py3-none-any.whl", hash = "sha256:46373ef69b6714f5064c923bb28bd797c4f8a9497f557d87fc36665c6d956b39"}, {file = "autoflake-1.7.8.tar.gz", hash = "sha256:e7e46372dee46fa1c97acf310d99d922b63d369718a270809d7c278d34a194cf"}, @@ -157,7 +149,6 @@ version = "1.7.2" description = "Security oriented static analyser for python code." optional = false python-versions = ">=3.7" -groups = ["dev"] files = [ {file = "bandit-1.7.2-py3-none-any.whl", hash = "sha256:e20402cadfd126d85b68ed4c8862959663c8c372dbbb1fca8f8e2c9f55a067ec"}, {file = "bandit-1.7.2.tar.gz", hash = "sha256:6d11adea0214a43813887bfe71a377b5a9955e4c826c8ffd341b494e3ab25260"}, @@ -180,7 +171,6 @@ version = "22.3.0" description = "The uncompromising code formatter." optional = false python-versions = ">=3.6.2" -groups = ["dev"] files = [ {file = "black-22.3.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:2497f9c2386572e28921fa8bec7be3e51de6801f7459dffd6e62492531c47e09"}, {file = "black-22.3.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5795a0375eb87bfe902e80e0c8cfaedf8af4d49694d69161e5bd3206c18618bb"}, @@ -227,7 +217,6 @@ version = "2024.6.2" description = "Python package for providing Mozilla's CA Bundle." optional = false python-versions = ">=3.6" -groups = ["main", "dev"] files = [ {file = "certifi-2024.6.2-py3-none-any.whl", hash = "sha256:ddc6c8ce995e6987e7faf5e3f1b02b302836a0e5d98ece18392cb1a36c72ad56"}, {file = "certifi-2024.6.2.tar.gz", hash = "sha256:3cd43f1c6fa7dedc5899d69d3ad0398fd018ad1a17fba83ddaf78aa46c747516"}, @@ -239,7 +228,6 @@ 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" -groups = ["dev"] files = [ {file = "charset-normalizer-3.3.2.tar.gz", hash = "sha256:f30c3cb33b24454a82faecaf01b19c18562b1e89558fb6c56de4d9118a032fd5"}, {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:25baf083bf6f6b341f4121c2f3c548875ee6f5339300e08be3f2b2ba1721cdd3"}, @@ -339,7 +327,6 @@ version = "8.1.7" description = "Composable command line interface toolkit" optional = false python-versions = ">=3.7" -groups = ["dev"] files = [ {file = "click-8.1.7-py3-none-any.whl", hash = "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28"}, {file = "click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de"}, @@ -354,12 +341,10 @@ version = "0.4.6" description = "Cross-platform colored terminal text." optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" -groups = ["main", "dev"] files = [ {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, ] -markers = {main = "sys_platform == \"win32\"", dev = "platform_system == \"Windows\" or sys_platform == \"win32\""} [[package]] name = "coverage" @@ -367,7 +352,6 @@ version = "7.5.4" description = "Code coverage measurement for Python" optional = false python-versions = ">=3.8" -groups = ["dev"] files = [ {file = "coverage-7.5.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:6cfb5a4f556bb51aba274588200a46e4dd6b505fb1a5f8c5ae408222eb416f99"}, {file = "coverage-7.5.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2174e7c23e0a454ffe12267a10732c273243b4f2d50d07544a91198f05c48f47"}, @@ -427,7 +411,7 @@ files = [ tomli = {version = "*", optional = true, markers = "python_full_version <= \"3.11.0a6\" and extra == \"toml\""} [package.extras] -toml = ["tomli ; python_full_version <= \"3.11.0a6\""] +toml = ["tomli"] [[package]] name = "darglint" @@ -435,7 +419,6 @@ version = "1.8.1" description = "A utility for ensuring Google-style docstrings stay up to date with the source code." optional = false python-versions = ">=3.6,<4.0" -groups = ["dev"] files = [ {file = "darglint-1.8.1-py3-none-any.whl", hash = "sha256:5ae11c259c17b0701618a20c3da343a3eb98b3bc4b5a83d31cdd94f5ebdced8d"}, {file = "darglint-1.8.1.tar.gz", hash = "sha256:080d5106df149b199822e7ee7deb9c012b49891538f14a11be681044f0bb20da"}, @@ -447,7 +430,6 @@ version = "0.20.1" description = "Docutils -- Python Documentation Utilities" optional = false python-versions = ">=3.7" -groups = ["dev"] files = [ {file = "docutils-0.20.1-py3-none-any.whl", hash = "sha256:96f387a2c5562db4476f09f13bbab2192e764cac08ebbf3a34a95d9b1e4a59d6"}, {file = "docutils-0.20.1.tar.gz", hash = "sha256:f08a4e276c3a1583a86dce3e34aba3fe04d02bba2dd51ed16106244e8a923e3b"}, @@ -459,7 +441,6 @@ version = "2.3.0" description = "Removes commented-out code." optional = false python-versions = "*" -groups = ["dev"] files = [ {file = "eradicate-2.3.0-py3-none-any.whl", hash = "sha256:2b29b3dd27171f209e4ddd8204b70c02f0682ae95eecb353f10e8d72b149c63e"}, {file = "eradicate-2.3.0.tar.gz", hash = "sha256:06df115be3b87d0fc1c483db22a2ebb12bcf40585722810d809cc770f5031c37"}, @@ -471,8 +452,6 @@ version = "1.2.1" description = "Backport of PEP 654 (exception groups)" optional = false python-versions = ">=3.7" -groups = ["main", "dev"] -markers = "python_version < \"3.11\"" files = [ {file = "exceptiongroup-1.2.1-py3-none-any.whl", hash = "sha256:5258b9ed329c5bbdd31a309f53cbfb0b155341807f6ff7606a1e801a891b29ad"}, {file = "exceptiongroup-1.2.1.tar.gz", hash = "sha256:a4785e48b045528f5bfe627b6ad554ff32def154f42372786903b7abcfe1aa16"}, @@ -481,13 +460,45 @@ files = [ [package.extras] test = ["pytest (>=6)"] +[[package]] +name = "factory-boy" +version = "3.3.3" +description = "A versatile test fixtures replacement based on thoughtbot's factory_bot for Ruby." +optional = false +python-versions = ">=3.8" +files = [ + {file = "factory_boy-3.3.3-py2.py3-none-any.whl", hash = "sha256:1c39e3289f7e667c4285433f305f8d506efc2fe9c73aaea4151ebd5cdea394fc"}, + {file = "factory_boy-3.3.3.tar.gz", hash = "sha256:866862d226128dfac7f2b4160287e899daf54f2612778327dd03d0e2cb1e3d03"}, +] + +[package.dependencies] +Faker = ">=0.7.0" + +[package.extras] +dev = ["Django", "Pillow", "SQLAlchemy", "coverage", "flake8", "isort", "mongoengine", "mongomock", "mypy", "tox", "wheel (>=0.32.0)", "zest.releaser[recommended]"] +doc = ["Sphinx", "sphinx-rtd-theme", "sphinxcontrib-spelling"] + +[[package]] +name = "faker" +version = "35.2.2" +description = "Faker is a Python package that generates fake data for you." +optional = false +python-versions = ">=3.8" +files = [ + {file = "Faker-35.2.2-py3-none-any.whl", hash = "sha256:94216ce3d8affdc0a8fd0ea8219c184c346a1dcf07b03f193e52f3116186621e"}, + {file = "faker-35.2.2.tar.gz", hash = "sha256:0a79ebe8f0ea803f7bd288d51e2d445b86035a2480e048daee1bffbd4d69b32b"}, +] + +[package.dependencies] +python-dateutil = ">=2.4" +typing-extensions = "*" + [[package]] name = "fastapi" version = "0.95.2" description = "FastAPI framework, high performance, easy to learn, fast to code, ready for production" optional = false python-versions = ">=3.7" -groups = ["dev"] files = [ {file = "fastapi-0.95.2-py3-none-any.whl", hash = "sha256:d374dbc4ef2ad9b803899bd3360d34c534adc574546e25314ab72c0c4411749f"}, {file = "fastapi-0.95.2.tar.gz", hash = "sha256:4d9d3e8c71c73f11874bcf5e33626258d143252e329a01002f767306c64fb982"}, @@ -509,7 +520,6 @@ version = "4.0.1" description = "the modular source code checker: pep8 pyflakes and co" optional = false python-versions = ">=3.6" -groups = ["dev"] files = [ {file = "flake8-4.0.1-py2.py3-none-any.whl", hash = "sha256:479b1304f72536a55948cb40a32dce8bb0ffe3501e26eaf292c7e60eb5e0428d"}, {file = "flake8-4.0.1.tar.gz", hash = "sha256:806e034dda44114815e23c16ef92f95c91e4c71100ff52813adf7132a6ad870d"}, @@ -526,7 +536,6 @@ version = "2.1.2" description = "Automated security testing with bandit and flake8." optional = false python-versions = "*" -groups = ["dev"] files = [ {file = "flake8_bandit-2.1.2.tar.gz", hash = "sha256:687fc8da2e4a239b206af2e54a90093572a60d0954f3054e23690739b0b0de3b"}, ] @@ -543,7 +552,6 @@ version = "0.4.0" description = "Flake8 plugin to forbid backslashes for line breaks" optional = false python-versions = ">=3.6,<4.0" -groups = ["dev"] files = [ {file = "flake8-broken-line-0.4.0.tar.gz", hash = "sha256:771aab5aa0997666796fed249d0e48e6c01cdfeca8c95521eea28a38b7ced4c7"}, {file = "flake8_broken_line-0.4.0-py3-none-any.whl", hash = "sha256:e9c522856862239a2c7ef2c1de0276fa598572aa864bd4e9c7efc2a827538515"}, @@ -558,7 +566,6 @@ version = "21.11.29" description = "A plugin for flake8 finding likely bugs and design problems in your program. Contains warnings that don't belong in pyflakes and pycodestyle." optional = false python-versions = ">=3.6" -groups = ["dev"] files = [ {file = "flake8-bugbear-21.11.29.tar.gz", hash = "sha256:8b04cb2fafc6a78e1a9d873bd3988e4282f7959bb6b0d7c1ae648ec09b937a7b"}, {file = "flake8_bugbear-21.11.29-py36.py37.py38-none-any.whl", hash = "sha256:179e41ddae5de5e3c20d1f61736feeb234e70958fbb56ab3c28a67739c8e9a82"}, @@ -577,7 +584,6 @@ version = "2.1.0" description = "Flake8 lint for trailing commas." optional = false python-versions = "*" -groups = ["dev"] files = [ {file = "flake8-commas-2.1.0.tar.gz", hash = "sha256:940441ab8ee544df564ae3b3f49f20462d75d5c7cac2463e0b27436e2050f263"}, {file = "flake8_commas-2.1.0-py2.py3-none-any.whl", hash = "sha256:ebb96c31e01d0ef1d0685a21f3f0e2f8153a0381430e748bf0bbbb5d5b453d54"}, @@ -592,7 +598,6 @@ version = "3.15.0" description = "A flake8 plugin to help you write better list/set/dict comprehensions." optional = false python-versions = ">=3.8" -groups = ["dev"] files = [ {file = "flake8_comprehensions-3.15.0-py3-none-any.whl", hash = "sha256:b7e027bbb52be2ceb779ee12484cdeef52b0ad3c1fcb8846292bdb86d3034681"}, {file = "flake8_comprehensions-3.15.0.tar.gz", hash = "sha256:923c22603e0310376a6b55b03efebdc09753c69f2d977755cba8bb73458a5d4d"}, @@ -607,7 +612,6 @@ version = "4.1.2" description = "ipdb/pdb statement checker plugin for flake8" optional = false python-versions = ">=3.7" -groups = ["dev"] files = [ {file = "flake8-debugger-4.1.2.tar.gz", hash = "sha256:52b002560941e36d9bf806fca2523dc7fb8560a295d5f1a6e15ac2ded7a73840"}, {file = "flake8_debugger-4.1.2-py3-none-any.whl", hash = "sha256:0a5e55aeddcc81da631ad9c8c366e7318998f83ff00985a49e6b3ecf61e571bf"}, @@ -623,7 +627,6 @@ version = "1.7.0" description = "Extension for flake8 which uses pydocstyle to check docstrings" optional = false python-versions = ">=3.7" -groups = ["dev"] files = [ {file = "flake8_docstrings-1.7.0-py2.py3-none-any.whl", hash = "sha256:51f2344026da083fc084166a9353f5082b01f72901df422f74b4d953ae88ac75"}, {file = "flake8_docstrings-1.7.0.tar.gz", hash = "sha256:4c8cc748dc16e6869728699e5d0d685da9a10b0ea718e090b1ba088e67a941af"}, @@ -639,7 +642,6 @@ version = "1.4.0" description = "Flake8 plugin to find commented out code" optional = false python-versions = ">=3.7,<4.0" -groups = ["dev"] files = [ {file = "flake8-eradicate-1.4.0.tar.gz", hash = "sha256:3088cfd6717d1c9c6c3ac45ef2e5f5b6c7267f7504d5a74b781500e95cb9c7e1"}, {file = "flake8_eradicate-1.4.0-py3-none-any.whl", hash = "sha256:e3bbd0871be358e908053c1ab728903c114f062ba596b4d40c852fd18f473d56"}, @@ -656,7 +658,6 @@ version = "4.2.0" description = "flake8 plugin that integrates isort ." optional = false python-versions = "*" -groups = ["dev"] files = [ {file = "flake8-isort-4.2.0.tar.gz", hash = "sha256:26571500cd54976bbc0cf1006ffbcd1a68dd102f816b7a1051b219616ba9fee0"}, {file = "flake8_isort-4.2.0-py3-none-any.whl", hash = "sha256:5b87630fb3719bf4c1833fd11e0d9534f43efdeba524863e15d8f14a7ef6adbf"}, @@ -675,7 +676,6 @@ version = "1.0.2" description = "Polyfill package for Flake8 plugins" optional = false python-versions = "*" -groups = ["dev"] files = [ {file = "flake8-polyfill-1.0.2.tar.gz", hash = "sha256:e44b087597f6da52ec6393a709e7108b2905317d0c0b744cdca6208e670d8eda"}, {file = "flake8_polyfill-1.0.2-py2.py3-none-any.whl", hash = "sha256:12be6a34ee3ab795b19ca73505e7b55826d5f6ad7230d31b18e106400169b9e9"}, @@ -690,7 +690,6 @@ version = "3.4.0" description = "Flake8 lint for quotes." optional = false python-versions = "*" -groups = ["dev"] files = [ {file = "flake8-quotes-3.4.0.tar.gz", hash = "sha256:aad8492fb710a2d3eabe68c5f86a1428de650c8484127e14c43d0504ba30276c"}, ] @@ -705,7 +704,6 @@ version = "0.2.7" description = "Python docstring reStructuredText (RST) validator" optional = false python-versions = ">=3.7" -groups = ["dev"] files = [ {file = "flake8-rst-docstrings-0.2.7.tar.gz", hash = "sha256:2740067ab9237559dd45a3434d8c987792c7b259ca563621a3b95efe201f5382"}, {file = "flake8_rst_docstrings-0.2.7-py3-none-any.whl", hash = "sha256:5d56075dce360bcc9c6775bfe7cb431aa395de600ca7e8d40580a28d50b2a803"}, @@ -722,7 +720,6 @@ version = "0.3.0" description = "string format checker, plugin for flake8" optional = false python-versions = "*" -groups = ["dev"] files = [ {file = "flake8-string-format-0.3.0.tar.gz", hash = "sha256:65f3da786a1461ef77fca3780b314edb2853c377f2e35069723348c8917deaa2"}, {file = "flake8_string_format-0.3.0-py2.py3-none-any.whl", hash = "sha256:812ff431f10576a74c89be4e85b8e075a705be39bc40c4b4278b5b13e2afa9af"}, @@ -737,7 +734,6 @@ version = "4.0.11" description = "Git Object Database" optional = false python-versions = ">=3.7" -groups = ["dev"] files = [ {file = "gitdb-4.0.11-py3-none-any.whl", hash = "sha256:81a3407ddd2ee8df444cbacea00e2d038e40150acfa3001696fe0dcf1d3adfa4"}, {file = "gitdb-4.0.11.tar.gz", hash = "sha256:bf5421126136d6d0af55bc1e7c1af1c397a34f5b7bd79e776cd3e89785c2b04b"}, @@ -752,7 +748,6 @@ version = "3.1.43" description = "GitPython is a Python library used to interact with Git repositories" optional = false python-versions = ">=3.7" -groups = ["dev"] files = [ {file = "GitPython-3.1.43-py3-none-any.whl", hash = "sha256:eec7ec56b92aad751f9912a73404bc02ba212a23adb2c7098ee668417051a1ff"}, {file = "GitPython-3.1.43.tar.gz", hash = "sha256:35f314a9f878467f5453cc1fee295c3e18e52f1b99f10f6cf5b1682e968a9e7c"}, @@ -763,7 +758,7 @@ gitdb = ">=4.0.1,<5" [package.extras] doc = ["sphinx (==4.3.2)", "sphinx-autodoc-typehints", "sphinx-rtd-theme", "sphinxcontrib-applehelp (>=1.0.2,<=1.0.4)", "sphinxcontrib-devhelp (==1.0.2)", "sphinxcontrib-htmlhelp (>=2.0.0,<=2.0.1)", "sphinxcontrib-qthelp (==1.0.3)", "sphinxcontrib-serializinghtml (==1.1.5)"] -test = ["coverage[toml]", "ddt (>=1.1.1,!=1.4.3)", "mock ; python_version < \"3.8\"", "mypy", "pre-commit", "pytest (>=7.3.1)", "pytest-cov", "pytest-instafail", "pytest-mock", "pytest-sugar", "typing-extensions ; python_version < \"3.11\""] +test = ["coverage[toml]", "ddt (>=1.1.1,!=1.4.3)", "mock", "mypy", "pre-commit", "pytest (>=7.3.1)", "pytest-cov", "pytest-instafail", "pytest-mock", "pytest-sugar", "typing-extensions"] [[package]] name = "h11" @@ -771,7 +766,6 @@ version = "0.16.0" description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" optional = false python-versions = ">=3.8" -groups = ["main", "dev"] files = [ {file = "h11-0.16.0-py3-none-any.whl", hash = "sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86"}, {file = "h11-0.16.0.tar.gz", hash = "sha256:4e35b956cf45792e4caa5885e69fba00bdbc6ffafbfa020300e549b208ee5ff1"}, @@ -783,7 +777,6 @@ version = "1.0.9" description = "A minimal low-level HTTP client." optional = false python-versions = ">=3.8" -groups = ["main", "dev"] files = [ {file = "httpcore-1.0.9-py3-none-any.whl", hash = "sha256:2d400746a40668fc9dec9810239072b40b4484b640a8c38fd654a024c7a1bf55"}, {file = "httpcore-1.0.9.tar.gz", hash = "sha256:6e34463af53fd2ab5d807f399a9b45ea31c3dfa2276f15a2c3f00afff6e176e8"}, @@ -805,7 +798,6 @@ version = "0.25.2" description = "The next generation HTTP client." optional = false python-versions = ">=3.8" -groups = ["main", "dev"] files = [ {file = "httpx-0.25.2-py3-none-any.whl", hash = "sha256:a05d3d052d9b2dfce0e3896636467f8a5342fb2b902c819428e1ac65413ca118"}, {file = "httpx-0.25.2.tar.gz", hash = "sha256:8b8fcaa0c8ea7b05edd69a094e63a2094c4efcb48129fb757361bc423c0ad9e8"}, @@ -819,7 +811,7 @@ idna = "*" sniffio = "*" [package.extras] -brotli = ["brotli ; platform_python_implementation == \"CPython\"", "brotlicffi ; platform_python_implementation != \"CPython\""] +brotli = ["brotli", "brotlicffi"] cli = ["click (==8.*)", "pygments (==2.*)", "rich (>=10,<14)"] http2 = ["h2 (>=3,<5)"] socks = ["socksio (==1.*)"] @@ -830,7 +822,6 @@ version = "3.7" description = "Internationalized Domain Names in Applications (IDNA)" optional = false python-versions = ">=3.5" -groups = ["main", "dev"] files = [ {file = "idna-3.7-py3-none-any.whl", hash = "sha256:82fee1fc78add43492d3a1898bfa6d8a904cc97d8427f683ed8e798d07761aa0"}, {file = "idna-3.7.tar.gz", hash = "sha256:028ff3aadf0609c1fd278d8ea3089299412a7a8b9bd005dd08b9f8285bcb5cfc"}, @@ -842,7 +833,6 @@ version = "2.0.0" description = "brain-dead simple config-ini parsing" optional = false python-versions = ">=3.7" -groups = ["dev"] files = [ {file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"}, {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, @@ -854,7 +844,6 @@ version = "5.10.1" description = "A Python utility / library to sort Python imports." optional = false python-versions = ">=3.6.1,<4.0" -groups = ["dev"] files = [ {file = "isort-5.10.1-py3-none-any.whl", hash = "sha256:6f62d78e2f89b4500b080fe3a81690850cd254227f27f75c3a0c491a1f351ba7"}, {file = "isort-5.10.1.tar.gz", hash = "sha256:e8443a5e7a020e9d7f97f1d7d9cd17c88bcb3bc7e218bf9cf5095fe550be2951"}, @@ -872,7 +861,6 @@ version = "0.6.0" description = "Python logging made (stupidly) simple" optional = false python-versions = ">=3.5" -groups = ["main"] files = [ {file = "loguru-0.6.0-py3-none-any.whl", hash = "sha256:4e2414d534a2ab57573365b3e6d0234dfb1d84b68b7f3b948e6fb743860a77c3"}, {file = "loguru-0.6.0.tar.gz", hash = "sha256:066bd06758d0a513e9836fd9c6b5a75bfb3fd36841f4b996bc60b547a309d41c"}, @@ -883,7 +871,7 @@ colorama = {version = ">=0.3.4", markers = "sys_platform == \"win32\""} win32-setctime = {version = ">=1.0.0", markers = "sys_platform == \"win32\""} [package.extras] -dev = ["Sphinx (>=4.1.1) ; python_version >= \"3.6\"", "black (>=19.10b0) ; python_version >= \"3.6\"", "colorama (>=0.3.4)", "docutils (==0.16)", "flake8 (>=3.7.7)", "isort (>=5.1.1) ; python_version >= \"3.6\"", "pytest (>=4.6.2)", "pytest-cov (>=2.7.1)", "sphinx-autobuild (>=0.7.1) ; python_version >= \"3.6\"", "sphinx-rtd-theme (>=0.4.3) ; python_version >= \"3.6\"", "tox (>=3.9.0)"] +dev = ["Sphinx (>=4.1.1)", "black (>=19.10b0)", "colorama (>=0.3.4)", "docutils (==0.16)", "flake8 (>=3.7.7)", "isort (>=5.1.1)", "pytest (>=4.6.2)", "pytest-cov (>=2.7.1)", "sphinx-autobuild (>=0.7.1)", "sphinx-rtd-theme (>=0.4.3)", "tox (>=3.9.0)"] [[package]] name = "mccabe" @@ -891,7 +879,6 @@ version = "0.6.1" description = "McCabe checker, plugin for flake8" optional = false python-versions = "*" -groups = ["dev"] files = [ {file = "mccabe-0.6.1-py2.py3-none-any.whl", hash = "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42"}, {file = "mccabe-0.6.1.tar.gz", hash = "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"}, @@ -903,7 +890,6 @@ version = "0.910" description = "Optional static typing for Python" optional = false python-versions = ">=3.5" -groups = ["dev"] files = [ {file = "mypy-0.910-cp35-cp35m-macosx_10_9_x86_64.whl", hash = "sha256:a155d80ea6cee511a3694b108c4494a39f42de11ee4e61e72bc424c490e46457"}, {file = "mypy-0.910-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:b94e4b785e304a04ea0828759172a15add27088520dc7e49ceade7834275bedb"}, @@ -945,7 +931,6 @@ version = "0.4.4" description = "Experimental type system extensions for programs checked with the mypy typechecker." optional = false python-versions = ">=2.7" -groups = ["main", "dev"] files = [ {file = "mypy_extensions-0.4.4.tar.gz", hash = "sha256:c8b707883a96efe9b4bb3aaf0dcc07e7e217d7d8368eec4db4049ee9e142f4fd"}, ] @@ -956,7 +941,6 @@ version = "24.1" description = "Core utilities for Python packages" optional = false python-versions = ">=3.8" -groups = ["dev"] files = [ {file = "packaging-24.1-py3-none-any.whl", hash = "sha256:5b8f2217dbdbd2f7f384c41c628544e6d52f2d0f53c6d0c3ea61aa5d1d7ff124"}, {file = "packaging-24.1.tar.gz", hash = "sha256:026ed72c8ed3fcce5bf8950572258698927fd1dbda10a5e981cdf0ac37f4f002"}, @@ -968,7 +952,6 @@ version = "0.12.1" description = "Utility library for gitignore style pattern matching of file paths." optional = false python-versions = ">=3.8" -groups = ["dev"] files = [ {file = "pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08"}, {file = "pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712"}, @@ -980,7 +963,6 @@ version = "6.0.0" description = "Python Build Reasonableness" optional = false python-versions = ">=2.6" -groups = ["dev"] files = [ {file = "pbr-6.0.0-py2.py3-none-any.whl", hash = "sha256:4a7317d5e3b17a3dccb6a8cfe67dab65b20551404c52c8ed41279fa4f0cb4cda"}, {file = "pbr-6.0.0.tar.gz", hash = "sha256:d1377122a5a00e2f940ee482999518efe16d745d423a670c27773dfbc3c9a7d9"}, @@ -992,7 +974,6 @@ version = "0.12.1" description = "Check PEP-8 naming conventions, plugin for flake8" optional = false python-versions = "*" -groups = ["dev"] files = [ {file = "pep8-naming-0.12.1.tar.gz", hash = "sha256:bb2455947757d162aa4cad55dba4ce029005cd1692f2899a21d51d8630ca7841"}, {file = "pep8_naming-0.12.1-py2.py3-none-any.whl", hash = "sha256:4a8daeaeb33cfcde779309fc0c9c0a68a3bbe2ad8a8308b763c5068f86eb9f37"}, @@ -1008,7 +989,6 @@ version = "4.2.2" description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`." optional = false python-versions = ">=3.8" -groups = ["dev"] files = [ {file = "platformdirs-4.2.2-py3-none-any.whl", hash = "sha256:2d7a1657e36a80ea911db832a8a6ece5ee53d8de21edd5cc5879af6530b1bfee"}, {file = "platformdirs-4.2.2.tar.gz", hash = "sha256:38b7b51f512eed9e84a22788b4bce1de17c0adb134d6becb09836e37d8654cd3"}, @@ -1025,7 +1005,6 @@ version = "1.5.0" description = "plugin and hook calling mechanisms for python" optional = false python-versions = ">=3.8" -groups = ["dev"] files = [ {file = "pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669"}, {file = "pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1"}, @@ -1041,7 +1020,6 @@ version = "2.8.0" description = "Python style guide checker" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -groups = ["dev"] files = [ {file = "pycodestyle-2.8.0-py2.py3-none-any.whl", hash = "sha256:720f8b39dde8b293825e7ff02c475f3077124006db4f440dcbc9a20b76548a20"}, {file = "pycodestyle-2.8.0.tar.gz", hash = "sha256:eddd5847ef438ea1c7870ca7eb78a9d47ce0cdb4851a5523949f2601d0cbbe7f"}, @@ -1053,7 +1031,6 @@ version = "1.10.17" description = "Data validation and settings management using python type hints" optional = false python-versions = ">=3.7" -groups = ["main", "dev"] files = [ {file = "pydantic-1.10.17-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0fa51175313cc30097660b10eec8ca55ed08bfa07acbfe02f7a42f6c242e9a4b"}, {file = "pydantic-1.10.17-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c7e8988bb16988890c985bd2093df9dd731bfb9d5e0860db054c23034fab8f7a"}, @@ -1113,7 +1090,6 @@ version = "6.3.0" description = "Python docstring style checker" optional = false python-versions = ">=3.6" -groups = ["dev"] files = [ {file = "pydocstyle-6.3.0-py3-none-any.whl", hash = "sha256:118762d452a49d6b05e194ef344a55822987a462831ade91ec5c06fd2169d019"}, {file = "pydocstyle-6.3.0.tar.gz", hash = "sha256:7ce43f0c0ac87b07494eb9c0b462c0b73e6ff276807f204d6b53edc72b7e44e1"}, @@ -1123,7 +1099,7 @@ files = [ snowballstemmer = ">=2.2.0" [package.extras] -toml = ["tomli (>=1.2.3) ; python_version < \"3.11\""] +toml = ["tomli (>=1.2.3)"] [[package]] name = "pyflakes" @@ -1131,7 +1107,6 @@ version = "2.4.0" description = "passive checker of Python programs" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -groups = ["dev"] files = [ {file = "pyflakes-2.4.0-py2.py3-none-any.whl", hash = "sha256:3bb3a3f256f4b7968c9c788781e4ff07dce46bdf12339dcda61053375426ee2e"}, {file = "pyflakes-2.4.0.tar.gz", hash = "sha256:05a85c2872edf37a4ed30b0cce2f6093e1d0581f8c19d7393122da7e25b2b24c"}, @@ -1143,7 +1118,6 @@ version = "2.18.0" description = "Pygments is a syntax highlighting package written in Python." optional = false python-versions = ">=3.8" -groups = ["dev"] files = [ {file = "pygments-2.18.0-py3-none-any.whl", hash = "sha256:b8e6aca0523f3ab76fee51799c488e38782ac06eafcf95e7ba832985c8e7b13a"}, {file = "pygments-2.18.0.tar.gz", hash = "sha256:786ff802f32e91311bff3889f6e9a86e81505fe99f2735bb6d60ae0c5004f199"}, @@ -1158,7 +1132,6 @@ version = "2.8.0" description = "JSON Web Token implementation in Python" optional = false python-versions = ">=3.7" -groups = ["main"] files = [ {file = "PyJWT-2.8.0-py3-none-any.whl", hash = "sha256:59127c392cc44c2da5bb3192169a91f429924e17aff6534d70fdc02ab3e04320"}, {file = "PyJWT-2.8.0.tar.gz", hash = "sha256:57e28d156e3d5c10088e0c68abb90bfac3df82b40a71bd0daa20c65ccd5c23de"}, @@ -1176,7 +1149,6 @@ version = "7.2.0" description = "pytest: simple powerful testing with Python" optional = false python-versions = ">=3.7" -groups = ["dev"] files = [ {file = "pytest-7.2.0-py3-none-any.whl", hash = "sha256:892f933d339f068883b6fd5a459f03d85bfcb355e4981e146d2c7616c21fef71"}, {file = "pytest-7.2.0.tar.gz", hash = "sha256:c4014eb40e10f11f355ad4e3c2fb2c6c6d1919c73f3b5a433de4708202cade59"}, @@ -1200,7 +1172,6 @@ version = "0.16.0" description = "Pytest support for asyncio." optional = false python-versions = ">= 3.6" -groups = ["dev"] files = [ {file = "pytest-asyncio-0.16.0.tar.gz", hash = "sha256:7496c5977ce88c34379df64a66459fe395cd05543f0a2f837016e7144391fcfb"}, {file = "pytest_asyncio-0.16.0-py3-none-any.whl", hash = "sha256:5f2a21273c47b331ae6aa5b36087047b4899e40f03f18397c0e65fa5cca54e9b"}, @@ -1218,7 +1189,6 @@ version = "4.0.0" description = "Pytest plugin for measuring coverage." optional = false python-versions = ">=3.6" -groups = ["dev"] files = [ {file = "pytest-cov-4.0.0.tar.gz", hash = "sha256:996b79efde6433cdbd0088872dbc5fb3ed7fe1578b68cdbba634f14bb8dd0470"}, {file = "pytest_cov-4.0.0-py3-none-any.whl", hash = "sha256:2feb1b751d66a8bd934e5edfa2e961d11309dc37b73b0eabe73b5945fee20f6b"}, @@ -1231,13 +1201,26 @@ pytest = ">=4.6" [package.extras] testing = ["fields", "hunter", "process-tests", "pytest-xdist", "six", "virtualenv"] +[[package]] +name = "python-dateutil" +version = "2.9.0.post0" +description = "Extensions to the standard Python datetime module" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" +files = [ + {file = "python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3"}, + {file = "python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427"}, +] + +[package.dependencies] +six = ">=1.5" + [[package]] name = "pyyaml" version = "6.0.1" description = "YAML parser and emitter for Python" optional = false python-versions = ">=3.6" -groups = ["dev"] files = [ {file = "PyYAML-6.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a"}, {file = "PyYAML-6.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f"}, @@ -1298,7 +1281,6 @@ version = "2.31.0" description = "Python HTTP for Humans." optional = false python-versions = ">=3.7" -groups = ["dev"] files = [ {file = "requests-2.31.0-py3-none-any.whl", hash = "sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f"}, {file = "requests-2.31.0.tar.gz", hash = "sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1"}, @@ -1320,7 +1302,6 @@ version = "0.20.2" description = "A utility for mocking out the Python HTTPX and HTTP Core libraries." optional = false python-versions = ">=3.7" -groups = ["dev"] files = [ {file = "respx-0.20.2-py2.py3-none-any.whl", hash = "sha256:ab8e1cf6da28a5b2dd883ea617f8130f77f676736e6e9e4a25817ad116a172c9"}, {file = "respx-0.20.2.tar.gz", hash = "sha256:07cf4108b1c88b82010f67d3c831dae33a375c7b436e54d87737c7f9f99be643"}, @@ -1335,7 +1316,6 @@ version = "1.4.0" description = "reStructuredText linter" optional = false python-versions = "*" -groups = ["dev"] files = [ {file = "restructuredtext_lint-1.4.0.tar.gz", hash = "sha256:1b235c0c922341ab6c530390892eb9e92f90b9b75046063e047cacfb0f050c45"}, ] @@ -1349,7 +1329,6 @@ version = "70.2.0" description = "Easily download, build, install, upgrade, and uninstall Python packages" optional = false python-versions = ">=3.8" -groups = ["dev"] files = [ {file = "setuptools-70.2.0-py3-none-any.whl", hash = "sha256:b8b8060bb426838fbe942479c90296ce976249451118ef566a5a0b7d8b78fb05"}, {file = "setuptools-70.2.0.tar.gz", hash = "sha256:bd63e505105011b25c3c11f753f7e3b8465ea739efddaccef8f0efac2137bac1"}, @@ -1357,7 +1336,18 @@ files = [ [package.extras] doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "pyproject-hooks (!=1.1)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier"] -test = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "importlib-metadata", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21) ; python_version >= \"3.9\" and sys_platform != \"cygwin\"", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "jaraco.test", "mypy (==1.10.0)", "packaging (>=23.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.*)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-home (>=0.5)", "pytest-mypy", "pytest-perf ; sys_platform != \"cygwin\"", "pytest-ruff (>=0.3.2) ; sys_platform != \"cygwin\"", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] +test = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "importlib-metadata", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "jaraco.test", "mypy (==1.10.0)", "packaging (>=23.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.*)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-home (>=0.5)", "pytest-mypy", "pytest-perf", "pytest-ruff (>=0.3.2)", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] + +[[package]] +name = "six" +version = "1.17.0" +description = "Python 2 and 3 compatibility utilities" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" +files = [ + {file = "six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274"}, + {file = "six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81"}, +] [[package]] name = "smmap" @@ -1365,7 +1355,6 @@ version = "5.0.1" description = "A pure Python implementation of a sliding window memory map manager" optional = false python-versions = ">=3.7" -groups = ["dev"] files = [ {file = "smmap-5.0.1-py3-none-any.whl", hash = "sha256:e6d8668fa5f93e706934a62d7b4db19c8d9eb8cf2adbb75ef1b675aa332b69da"}, {file = "smmap-5.0.1.tar.gz", hash = "sha256:dceeb6c0028fdb6734471eb07c0cd2aae706ccaecab45965ee83f11c8d3b1f62"}, @@ -1377,7 +1366,6 @@ version = "1.3.1" description = "Sniff out which async library your code is running under" optional = false python-versions = ">=3.7" -groups = ["main", "dev"] files = [ {file = "sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2"}, {file = "sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc"}, @@ -1389,7 +1377,6 @@ version = "2.2.0" description = "This package provides 29 stemmers for 28 languages generated from Snowball algorithms." optional = false python-versions = "*" -groups = ["dev"] files = [ {file = "snowballstemmer-2.2.0-py2.py3-none-any.whl", hash = "sha256:c8e1716e83cc398ae16824e5572ae04e0d9fc2c6b985fb0f900f5f0c96ecba1a"}, {file = "snowballstemmer-2.2.0.tar.gz", hash = "sha256:09b16deb8547d3412ad7b590689584cd0fe25ec8db3be37788be3810cbf19cb1"}, @@ -1401,7 +1388,6 @@ version = "0.27.0" description = "The little ASGI library that shines." optional = false python-versions = ">=3.7" -groups = ["dev"] files = [ {file = "starlette-0.27.0-py3-none-any.whl", hash = "sha256:918416370e846586541235ccd38a474c08b80443ed31c578a418e2209b3eef91"}, {file = "starlette-0.27.0.tar.gz", hash = "sha256:6a6b0d042acb8d469a01eba54e9cda6cbd24ac602c4cd016723117d6a7e73b75"}, @@ -1420,7 +1406,6 @@ version = "5.2.0" description = "Manage dynamic plugins for Python applications" optional = false python-versions = ">=3.8" -groups = ["dev"] files = [ {file = "stevedore-5.2.0-py3-none-any.whl", hash = "sha256:1c15d95766ca0569cad14cb6272d4d31dae66b011a929d7c18219c176ea1b5c9"}, {file = "stevedore-5.2.0.tar.gz", hash = "sha256:46b93ca40e1114cea93d738a6c1e365396981bb6bb78c27045b7587c9473544d"}, @@ -1435,7 +1420,6 @@ version = "5.2.0" description = "A wrapper around the stdlib `tokenize` which roundtrips." optional = false python-versions = ">=3.8" -groups = ["dev"] files = [ {file = "tokenize_rt-5.2.0-py2.py3-none-any.whl", hash = "sha256:b79d41a65cfec71285433511b50271b05da3584a1da144a0752e9c621a285289"}, {file = "tokenize_rt-5.2.0.tar.gz", hash = "sha256:9fe80f8a5c1edad2d3ede0f37481cc0cc1538a2f442c9c2f9e4feacd2792d054"}, @@ -1447,7 +1431,6 @@ version = "0.10.2" description = "Python Library for Tom's Obvious, Minimal Language" optional = false python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" -groups = ["dev"] files = [ {file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"}, {file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"}, @@ -1459,8 +1442,6 @@ version = "2.0.1" description = "A lil' TOML parser" optional = false python-versions = ">=3.7" -groups = ["dev"] -markers = "python_full_version <= \"3.11.0a6\"" files = [ {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, @@ -1472,7 +1453,6 @@ version = "4.12.2" description = "Backported and Experimental Type Hints for Python 3.8+" optional = false python-versions = ">=3.8" -groups = ["main", "dev"] files = [ {file = "typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d"}, {file = "typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8"}, @@ -1484,14 +1464,13 @@ version = "2.2.2" description = "HTTP library with thread-safe connection pooling, file post, and more." optional = false python-versions = ">=3.8" -groups = ["dev"] files = [ {file = "urllib3-2.2.2-py3-none-any.whl", hash = "sha256:a448b2f64d686155468037e1ace9f2d2199776e17f0a46610480d311f73e3472"}, {file = "urllib3-2.2.2.tar.gz", hash = "sha256:dd505485549a7a552833da5e6063639d0d177c04f23bc3864e41e5dc5f612168"}, ] [package.extras] -brotli = ["brotli (>=1.0.9) ; platform_python_implementation == \"CPython\"", "brotlicffi (>=0.8.0) ; platform_python_implementation != \"CPython\""] +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)"] @@ -1502,7 +1481,6 @@ version = "0.16.0" description = "The lightning-fast ASGI server." optional = false python-versions = "*" -groups = ["dev"] files = [ {file = "uvicorn-0.16.0-py3-none-any.whl", hash = "sha256:d8c839231f270adaa6d338d525e2652a0b4a5f4c2430b5c4ef6ae4d11776b0d2"}, {file = "uvicorn-0.16.0.tar.gz", hash = "sha256:eacb66afa65e0648fcbce5e746b135d09722231ffffc61883d4fac2b62fbea8d"}, @@ -1514,7 +1492,7 @@ click = ">=7.0" h11 = ">=0.8" [package.extras] -standard = ["PyYAML (>=5.1)", "colorama (>=0.4) ; sys_platform == \"win32\"", "httptools (>=0.2.0,<0.4.0)", "python-dotenv (>=0.13)", "uvloop (>=0.14.0,!=0.15.0,!=0.15.1) ; sys_platform != \"win32\" and sys_platform != \"cygwin\" and platform_python_implementation != \"PyPy\"", "watchgod (>=0.6)", "websockets (>=10.0) ; python_version >= \"3.7\"", "websockets (>=9.1) ; python_version < \"3.7\""] +standard = ["PyYAML (>=5.1)", "colorama (>=0.4)", "httptools (>=0.2.0,<0.4.0)", "python-dotenv (>=0.13)", "uvloop (>=0.14.0,!=0.15.0,!=0.15.1)", "watchgod (>=0.6)", "websockets (>=10.0)", "websockets (>=9.1)"] [[package]] name = "wemake-python-styleguide" @@ -1522,7 +1500,6 @@ version = "0.16.0" description = "The strictest and most opinionated python linter ever" optional = false python-versions = ">=3.6,<4.0" -groups = ["dev"] files = [ {file = "wemake-python-styleguide-0.16.0.tar.gz", hash = "sha256:3bf0a4962404e6fd6fa479e72e2ba3fb75d5920ea6c44b72b45240c9e519543c"}, {file = "wemake_python_styleguide-0.16.0-py3-none-any.whl", hash = "sha256:8caa92b4aa77b08a505d718553238812d1b612b1036bc171ca3aa18345efe0b4"}, @@ -1555,17 +1532,15 @@ version = "1.1.0" description = "A small Python utility to set file creation time on Windows" optional = false python-versions = ">=3.5" -groups = ["main"] -markers = "sys_platform == \"win32\"" files = [ {file = "win32_setctime-1.1.0-py3-none-any.whl", hash = "sha256:231db239e959c2fe7eb1d7dc129f11172354f98361c4fa2d6d2d7e278baa8aad"}, {file = "win32_setctime-1.1.0.tar.gz", hash = "sha256:15cf5750465118d6929ae4de4eb46e8edae9a5634350c01ba582df868e932cb2"}, ] [package.extras] -dev = ["black (>=19.3b0) ; python_version >= \"3.6\"", "pytest (>=4.6.2)"] +dev = ["black (>=19.3b0)", "pytest (>=4.6.2)"] [metadata] -lock-version = "2.1" +lock-version = "2.0" python-versions = ">=3.8,<3.13" -content-hash = "667e5646840fb17ff48f2ee93042ecce0aa94e0a263ceac95e2b8d7ae95e118d" +content-hash = "b8ce40af6fb0b43689c9688efec660387d518934f411557da6080a18189ee3ed" diff --git a/pybotx/bot/handler.py b/pybotx/bot/handler.py index 22345003..d5a4c470 100644 --- a/pybotx/bot/handler.py +++ b/pybotx/bot/handler.py @@ -18,6 +18,7 @@ ) from pybotx.models.system_events.left_from_chat import LeftFromChatEvent from pybotx.models.system_events.smartapp_event import SmartAppEvent +from pybotx.models.system_events.user_joined_to_chat import JoinToChatEvent if TYPE_CHECKING: # To avoid circular import from pybotx.bot.bot import Bot @@ -42,6 +43,7 @@ HandlerFunc[InternalBotNotificationEvent], HandlerFunc[SmartAppEvent], HandlerFunc[EventEdit], + HandlerFunc[JoinToChatEvent], ] VisibleFunc = Callable[[StatusRecipient, "Bot"], Awaitable[bool]] diff --git a/pybotx/bot/handler_collector.py b/pybotx/bot/handler_collector.py index 5b5d88ca..f42576ff 100644 --- a/pybotx/bot/handler_collector.py +++ b/pybotx/bot/handler_collector.py @@ -51,6 +51,7 @@ ) from pybotx.models.system_events.left_from_chat import LeftFromChatEvent from pybotx.models.system_events.smartapp_event import SmartAppEvent +from pybotx.models.system_events.user_joined_to_chat import JoinToChatEvent if TYPE_CHECKING: # To avoid circular import from pybotx.bot.bot import Bot @@ -269,6 +270,14 @@ def left_from_chat( self._system_event(LeftFromChatEvent, handler_func) return handler_func + def user_joined_to_chat( + self, + handler_func: HandlerFunc[JoinToChatEvent], + ) -> HandlerFunc[JoinToChatEvent]: + """Decorate `user_joined_to_chat` event handler.""" + self._system_event(JoinToChatEvent, handler_func) + return handler_func + def internal_bot_notification( self, handler_func: HandlerFunc[InternalBotNotificationEvent], diff --git a/pybotx/models/commands.py b/pybotx/models/commands.py index 3162457b..ed9fc902 100644 --- a/pybotx/models/commands.py +++ b/pybotx/models/commands.py @@ -32,6 +32,10 @@ BotAPISmartAppEvent, SmartAppEvent, ) +from pybotx.models.system_events.user_joined_to_chat import ( + BotAPIJoinToChat, + JoinToChatEvent, +) # Sorted by frequency of occurrence to speedup validation BotAPISystemEvent = Union[ @@ -45,6 +49,7 @@ BotAPICTSLogin, BotAPICTSLogout, BotAPIEventEdit, + BotAPIJoinToChat, ] BotAPICommand = Union[BotAPIIncomingMessage, BotAPISystemEvent] @@ -60,5 +65,6 @@ CTSLoginEvent, CTSLogoutEvent, EventEdit, + JoinToChatEvent, ] BotCommand = Union[IncomingMessage, SystemEvent] diff --git a/pybotx/models/enums.py b/pybotx/models/enums.py index a37ce06c..91c6fe90 100644 --- a/pybotx/models/enums.py +++ b/pybotx/models/enums.py @@ -103,6 +103,7 @@ class BotAPISystemEventTypes(StrEnum): LEFT_FROM_CHAT = "system:left_from_chat" SMARTAPP_EVENT = "system:smartapp_event" EVENT_EDIT = "system:event_edit" + JOIN_TO_CHAT = "system:user_joined_to_chat" class BotAPIClientPlatforms(Enum): diff --git a/pybotx/models/system_events/user_joined_to_chat.py b/pybotx/models/system_events/user_joined_to_chat.py new file mode 100644 index 00000000..0b36e2d8 --- /dev/null +++ b/pybotx/models/system_events/user_joined_to_chat.py @@ -0,0 +1,94 @@ +from dataclasses import dataclass +from typing import Any, Dict, List, Literal +from uuid import UUID + +from pydantic import Field + +from pybotx.models.api_base import VerifiedPayloadBaseModel +from pybotx.models.base_command import ( + BotAPIBaseCommand, + BotAPIBaseSystemEventPayload, + BotAPIChatContext, + BotCommandBase, +) +from pybotx.models.bot_account import BotAccount +from pybotx.models.chats import Chat +from pybotx.models.enums import BotAPISystemEventTypes, convert_chat_type_to_domain + + +@dataclass +class JoinToChatEvent(BotCommandBase): + """Domain model for user joined to chat event. + + This model represents the domain entity for system:user_joined_to_chat events + after being converted from the API representation. + + Attributes: + bot: The bot account that received the event. + raw_command: The original raw command dictionary. + huids: List of UUIDs of users who joined the chat. + chat: The chat that users joined. + """ + + huids: List[UUID] + chat: Chat + + +class BotAPIJoinToChatData(VerifiedPayloadBaseModel): + """Data model for user joined to chat event. + + This model represents the data field in the BotX API payload + for system:user_joined_to_chat events. + + Attributes: + added_members: List of UUIDs of users who joined the chat. + """ + + added_members: List[UUID] + + +class BotAPIJoinToChatPayload(BotAPIBaseSystemEventPayload): + """Payload model for user joined to chat event. + + This model represents the command field in the BotX API request + for system:user_joined_to_chat events. + + Attributes: + body: Literal value of BotAPISystemEventTypes.JOIN_TO_CHAT. + data: The data containing information about users who joined. + """ + + body: Literal[BotAPISystemEventTypes.JOIN_TO_CHAT] + data: BotAPIJoinToChatData + + +class BotAPIJoinToChat(BotAPIBaseCommand): + """API model for user joined to chat event. + + This model represents the complete BotX API request structure + for system:user_joined_to_chat events. + + Attributes: + payload: The command payload with event data. + sender: The chat context information. + """ + + payload: BotAPIJoinToChatPayload = Field(..., alias="command") + sender: BotAPIChatContext = Field(..., alias="from") + + def to_domain(self, raw_command: Dict[str, Any]) -> JoinToChatEvent: + return JoinToChatEvent( + bot=BotAccount( + id=self.bot_id, + host=self.sender.host, + ), + raw_command=raw_command, + huids=self.payload.data.added_members, + chat=Chat( + id=self.sender.group_chat_id, + type=convert_chat_type_to_domain(self.sender.chat_type), + ), + ) + + class Config: + allow_population_by_field_name = True diff --git a/pyproject.toml b/pyproject.toml index 98404536..b97e4684 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "pybotx" -version = "0.73.4" +version = "0.73.5" description = "A python library for interacting with eXpress BotX API" authors = [ "Sidnev Nikolay ", @@ -46,6 +46,7 @@ respx = "0.20.2" fastapi = "0.95.2" starlette = "0.27.0" # TODO: Drop dependency after updating end-to-end test uvicorn = "0.16.0" +factory-boy = "3.3.3" [build-system] requires = ["poetry>=0.12"] diff --git a/setup.cfg b/setup.cfg index bb108bcf..672a5d43 100644 --- a/setup.cfg +++ b/setup.cfg @@ -47,7 +47,7 @@ show-source = true max-line-length = 88 inline-quotes = double -nested_classes_whitelist = Config +nested_classes_whitelist = Config, Meta allowed_domain_names = data, handler, result, content, file per-file-ignores = diff --git a/tests/system_events/factories.py b/tests/system_events/factories.py new file mode 100644 index 00000000..2882f725 --- /dev/null +++ b/tests/system_events/factories.py @@ -0,0 +1,66 @@ +import uuid +from typing import Any, Dict, List, Optional + +from factory.base import DictFactory +from factory.declarations import SubFactory + + +class DeviceMetaFactory(DictFactory): + + permissions: Optional[str] = None + pushes: Optional[str] = None + timezone: Optional[str] = None + + +class FromFactory(DictFactory): + user_huid: Optional[str] = None + group_chat_id: str = "8dada2c8-67a6-4434-9dec-570d244e78ee" + ad_login: Optional[str] = None + ad_domain: Optional[str] = None + username: Optional[str] = None + chat_type: str = "group_chat" + manufacturer: Optional[str] = None + device: Optional[str] = None + device_software: Optional[str] = None + device_meta: Dict[str, Any] = SubFactory(DeviceMetaFactory) # type: ignore # noqa: F821 + platform: Optional[str] = None + platform_package_id: Optional[str] = None + is_admin: Optional[bool] = None + is_creator: Optional[bool] = None + app_version: Optional[str] = None + locale: str = "en" + host: str = "cts.ccteam.ru" + + +class CommandDataFactory(DictFactory): + + added_members: List[str] = [uuid.uuid4().hex, uuid.uuid4().hex] + + +class CommandFactory(DictFactory): + + body: str = "system:user_joined_to_chat" + command_type: str = "system" + data: Dict[str, Any] = SubFactory(CommandDataFactory) # type: ignore # noqa: F821 + metadata: Dict[str, Any] = {} + + class Meta: + model = dict + + +class BotAPIJoinToChatFactory(DictFactory): + + sync_id: str = uuid.uuid4().hex + command: Dict[str, Any] = SubFactory(CommandFactory) # type: ignore # noqa: F821 + async_files: List[str] = [] + attachments: List[str] = [] + entities: List[str] = [] + from_: Dict[str, Any] = SubFactory( + FromFactory, + ) # type: ignore # noqa: F821 + bot_id: str = uuid.uuid4().hex + proto_version: int = 4 + source_sync_id: Optional[str] = None + + class Meta: + rename = {"from_": "from"} diff --git a/tests/system_events/test_join_to_chat.py b/tests/system_events/test_join_to_chat.py new file mode 100644 index 00000000..6b66fbd4 --- /dev/null +++ b/tests/system_events/test_join_to_chat.py @@ -0,0 +1,68 @@ +from typing import Any, Optional +from uuid import UUID + +import pytest + +from pybotx import ( + Bot, + BotAccount, + BotAccountWithSecret, + Chat, + ChatTypes, + HandlerCollector, + lifespan_wrapper, +) +from pybotx.models.system_events.user_joined_to_chat import JoinToChatEvent +from tests.system_events.factories import BotAPIJoinToChatFactory # type: ignore + +pytestmark = [ + pytest.mark.asyncio, + pytest.mark.mock_authorization, + pytest.mark.usefixtures("respx_mock"), +] + + +async def test__join_to_chat__succeed( + bot_account: BotAccountWithSecret, +) -> None: + """Verifies user joining chat message processing. + + The test checks that: + 1. The system:user_joined_to_chat event is properly routed + 2. The event data is correctly converted to a UserJoinedToChatEvent object + 3. The registered user_joined_to_chat handler is called with this event + """ + + payload: dict[str, Any] = BotAPIJoinToChatFactory(bot_id=bot_account.id.hex) + + collector = HandlerCollector() + join_to_chat: Optional[JoinToChatEvent] = None + + @collector.user_joined_to_chat + async def join_to_chat_handler(event: JoinToChatEvent, bot: Bot) -> None: + nonlocal join_to_chat + join_to_chat = event + # Drop `raw_command` from asserting + join_to_chat.raw_command = None + + built_bot = Bot(collectors=[collector], bot_accounts=[bot_account]) + + # - Act - + async with lifespan_wrapper(built_bot) as bot: + bot.async_execute_raw_bot_command(payload, verify_request=False) + + # - Assert - + expected_event = JoinToChatEvent( + bot=BotAccount( + id=bot_account.id, + host=payload["from"]["host"], + ), + raw_command=None, + huids=list(map(UUID, payload["command"]["data"]["added_members"])), + chat=Chat( + id=UUID(payload["from"]["group_chat_id"]), + type=ChatTypes.GROUP_CHAT, + ), + ) + + assert join_to_chat == expected_event From d2df3548a9ba2c0bfb5066e57e8335c5854f72e6 Mon Sep 17 00:00:00 2001 From: vladimirgubarik Date: Wed, 7 May 2025 10:17:45 +0300 Subject: [PATCH 2/3] feature: downgrade factory boy to 3.3.1 --- poetry.lock | 8 ++++---- pyproject.toml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/poetry.lock b/poetry.lock index c8159139..18a8362b 100644 --- a/poetry.lock +++ b/poetry.lock @@ -462,13 +462,13 @@ test = ["pytest (>=6)"] [[package]] name = "factory-boy" -version = "3.3.3" +version = "3.3.1" description = "A versatile test fixtures replacement based on thoughtbot's factory_bot for Ruby." optional = false python-versions = ">=3.8" files = [ - {file = "factory_boy-3.3.3-py2.py3-none-any.whl", hash = "sha256:1c39e3289f7e667c4285433f305f8d506efc2fe9c73aaea4151ebd5cdea394fc"}, - {file = "factory_boy-3.3.3.tar.gz", hash = "sha256:866862d226128dfac7f2b4160287e899daf54f2612778327dd03d0e2cb1e3d03"}, + {file = "factory_boy-3.3.1-py2.py3-none-any.whl", hash = "sha256:7b1113c49736e1e9995bc2a18f4dbf2c52cf0f841103517010b1d825712ce3ca"}, + {file = "factory_boy-3.3.1.tar.gz", hash = "sha256:8317aa5289cdfc45f9cae570feb07a6177316c82e34d14df3c2e1f22f26abef0"}, ] [package.dependencies] @@ -1543,4 +1543,4 @@ dev = ["black (>=19.3b0)", "pytest (>=4.6.2)"] [metadata] lock-version = "2.0" python-versions = ">=3.8,<3.13" -content-hash = "b8ce40af6fb0b43689c9688efec660387d518934f411557da6080a18189ee3ed" +content-hash = "49691dc51a566fa9c00e4e9aa9182bf29336561c505378c72fe1fca6312c212e" diff --git a/pyproject.toml b/pyproject.toml index b97e4684..ebae433d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -46,7 +46,7 @@ respx = "0.20.2" fastapi = "0.95.2" starlette = "0.27.0" # TODO: Drop dependency after updating end-to-end test uvicorn = "0.16.0" -factory-boy = "3.3.3" +factory-boy = "3.3.1" [build-system] requires = ["poetry>=0.12"] From ac543e920c9aeef17e9dcbb08fd7960adf37593a Mon Sep 17 00:00:00 2001 From: vladimirgubarik Date: Wed, 7 May 2025 10:34:36 +0300 Subject: [PATCH 3/3] feature: fix lint issues --- tests/system_events/factories.py | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/tests/system_events/factories.py b/tests/system_events/factories.py index 2882f725..a83ec774 100644 --- a/tests/system_events/factories.py +++ b/tests/system_events/factories.py @@ -1,18 +1,18 @@ import uuid from typing import Any, Dict, List, Optional -from factory.base import DictFactory -from factory.declarations import SubFactory +from factory.base import DictFactory # type: ignore +from factory.declarations import SubFactory # type: ignore -class DeviceMetaFactory(DictFactory): +class DeviceMetaFactory(DictFactory): # type: ignore[misc] permissions: Optional[str] = None pushes: Optional[str] = None timezone: Optional[str] = None -class FromFactory(DictFactory): +class FromFactory(DictFactory): # type: ignore[misc] user_huid: Optional[str] = None group_chat_id: str = "8dada2c8-67a6-4434-9dec-570d244e78ee" ad_login: Optional[str] = None @@ -22,7 +22,7 @@ class FromFactory(DictFactory): manufacturer: Optional[str] = None device: Optional[str] = None device_software: Optional[str] = None - device_meta: Dict[str, Any] = SubFactory(DeviceMetaFactory) # type: ignore # noqa: F821 + device_meta: Dict[str, Any] = SubFactory(DeviceMetaFactory) # noqa: F821 platform: Optional[str] = None platform_package_id: Optional[str] = None is_admin: Optional[bool] = None @@ -32,32 +32,29 @@ class FromFactory(DictFactory): host: str = "cts.ccteam.ru" -class CommandDataFactory(DictFactory): +class CommandDataFactory(DictFactory): # type: ignore[misc] added_members: List[str] = [uuid.uuid4().hex, uuid.uuid4().hex] -class CommandFactory(DictFactory): +class CommandFactory(DictFactory): # type: ignore[misc] body: str = "system:user_joined_to_chat" command_type: str = "system" - data: Dict[str, Any] = SubFactory(CommandDataFactory) # type: ignore # noqa: F821 + data: Dict[str, Any] = SubFactory(CommandDataFactory) # noqa: F821 metadata: Dict[str, Any] = {} - class Meta: - model = dict - -class BotAPIJoinToChatFactory(DictFactory): +class BotAPIJoinToChatFactory(DictFactory): # type: ignore[misc] sync_id: str = uuid.uuid4().hex - command: Dict[str, Any] = SubFactory(CommandFactory) # type: ignore # noqa: F821 + command: Dict[str, Any] = SubFactory(CommandFactory) # noqa: F821 async_files: List[str] = [] attachments: List[str] = [] entities: List[str] = [] from_: Dict[str, Any] = SubFactory( FromFactory, - ) # type: ignore # noqa: F821 + ) # noqa: F821 bot_id: str = uuid.uuid4().hex proto_version: int = 4 source_sync_id: Optional[str] = None