diff --git a/poetry.lock b/poetry.lock index ef946cb75..823812c1b 100644 --- a/poetry.lock +++ b/poetry.lock @@ -171,52 +171,6 @@ files = [ tests = ["pytest (>=3.2.1,!=3.3.0)"] typecheck = ["mypy"] -[[package]] -name = "black" -version = "24.4.2" -description = "The uncompromising code formatter." -optional = false -python-versions = ">=3.8" -files = [ - {file = "black-24.4.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:dd1b5a14e417189db4c7b64a6540f31730713d173f0b63e55fabd52d61d8fdce"}, - {file = "black-24.4.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8e537d281831ad0e71007dcdcbe50a71470b978c453fa41ce77186bbe0ed6021"}, - {file = "black-24.4.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eaea3008c281f1038edb473c1aa8ed8143a5535ff18f978a318f10302b254063"}, - {file = "black-24.4.2-cp310-cp310-win_amd64.whl", hash = "sha256:7768a0dbf16a39aa5e9a3ded568bb545c8c2727396d063bbaf847df05b08cd96"}, - {file = "black-24.4.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:257d724c2c9b1660f353b36c802ccece186a30accc7742c176d29c146df6e474"}, - {file = "black-24.4.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:bdde6f877a18f24844e381d45e9947a49e97933573ac9d4345399be37621e26c"}, - {file = "black-24.4.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e151054aa00bad1f4e1f04919542885f89f5f7d086b8a59e5000e6c616896ffb"}, - {file = "black-24.4.2-cp311-cp311-win_amd64.whl", hash = "sha256:7e122b1c4fb252fd85df3ca93578732b4749d9be076593076ef4d07a0233c3e1"}, - {file = "black-24.4.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:accf49e151c8ed2c0cdc528691838afd217c50412534e876a19270fea1e28e2d"}, - {file = "black-24.4.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:88c57dc656038f1ab9f92b3eb5335ee9b021412feaa46330d5eba4e51fe49b04"}, - {file = "black-24.4.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:be8bef99eb46d5021bf053114442914baeb3649a89dc5f3a555c88737e5e98fc"}, - {file = "black-24.4.2-cp312-cp312-win_amd64.whl", hash = "sha256:415e686e87dbbe6f4cd5ef0fbf764af7b89f9057b97c908742b6008cc554b9c0"}, - {file = "black-24.4.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:bf10f7310db693bb62692609b397e8d67257c55f949abde4c67f9cc574492cc7"}, - {file = "black-24.4.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:98e123f1d5cfd42f886624d84464f7756f60ff6eab89ae845210631714f6db94"}, - {file = "black-24.4.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:48a85f2cb5e6799a9ef05347b476cce6c182d6c71ee36925a6c194d074336ef8"}, - {file = "black-24.4.2-cp38-cp38-win_amd64.whl", hash = "sha256:b1530ae42e9d6d5b670a34db49a94115a64596bc77710b1d05e9801e62ca0a7c"}, - {file = "black-24.4.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:37aae07b029fa0174d39daf02748b379399b909652a806e5708199bd93899da1"}, - {file = "black-24.4.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:da33a1a5e49c4122ccdfd56cd021ff1ebc4a1ec4e2d01594fef9b6f267a9e741"}, - {file = "black-24.4.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ef703f83fc32e131e9bcc0a5094cfe85599e7109f896fe8bc96cc402f3eb4b6e"}, - {file = "black-24.4.2-cp39-cp39-win_amd64.whl", hash = "sha256:b9176b9832e84308818a99a561e90aa479e73c523b3f77afd07913380ae2eab7"}, - {file = "black-24.4.2-py3-none-any.whl", hash = "sha256:d36ed1124bb81b32f8614555b34cc4259c3fbc7eec17870e8ff8ded335b58d8c"}, - {file = "black-24.4.2.tar.gz", hash = "sha256:c872b53057f000085da66a19c55d68f6f8ddcac2642392ad3a355878406fbd4d"}, -] - -[package.dependencies] -click = ">=8.0.0" -mypy-extensions = ">=0.4.3" -packaging = ">=22.0" -pathspec = ">=0.9.0" -platformdirs = ">=2" -tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} -typing-extensions = {version = ">=4.0.1", markers = "python_version < \"3.11\""} - -[package.extras] -colorama = ["colorama (>=0.4.3)"] -d = ["aiohttp (>=3.7.4)", "aiohttp (>=3.7.4,!=3.9.0)"] -jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] -uvloop = ["uvloop (>=0.15.2)"] - [[package]] name = "cachetools" version = "5.3.3" @@ -402,20 +356,6 @@ files = [ {file = "charset_normalizer-3.3.2-py3-none-any.whl", hash = "sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc"}, ] -[[package]] -name = "click" -version = "8.1.7" -description = "Composable command line interface toolkit" -optional = false -python-versions = ">=3.7" -files = [ - {file = "click-8.1.7-py3-none-any.whl", hash = "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28"}, - {file = "click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de"}, -] - -[package.dependencies] -colorama = {version = "*", markers = "platform_system == \"Windows\""} - [[package]] name = "codespell" version = "2.3.0" @@ -651,68 +591,6 @@ files = [ [package.extras] tests = ["asttokens (>=2.1.0)", "coverage", "coverage-enable-subprocess", "ipython", "littleutils", "pytest", "rich"] -[[package]] -name = "flake8" -version = "7.0.0" -description = "the modular source code checker: pep8 pyflakes and co" -optional = false -python-versions = ">=3.8.1" -files = [ - {file = "flake8-7.0.0-py2.py3-none-any.whl", hash = "sha256:a6dfbb75e03252917f2473ea9653f7cd799c3064e54d4c8140044c5c065f53c3"}, - {file = "flake8-7.0.0.tar.gz", hash = "sha256:33f96621059e65eec474169085dc92bf26e7b2d47366b70be2f67ab80dc25132"}, -] - -[package.dependencies] -mccabe = ">=0.7.0,<0.8.0" -pycodestyle = ">=2.11.0,<2.12.0" -pyflakes = ">=3.2.0,<3.3.0" - -[[package]] -name = "flake8-builtins" -version = "2.5.0" -description = "Check for python builtins being used as variables or parameters" -optional = false -python-versions = ">=3.8" -files = [ - {file = "flake8_builtins-2.5.0-py3-none-any.whl", hash = "sha256:8cac7c52c6f0708c0902b46b385bc7e368a9068965083796f1431c0d2e6550cf"}, - {file = "flake8_builtins-2.5.0.tar.gz", hash = "sha256:bdaa3dd823e4f5308c5e712d19fa5f69daa52781ea874f5ea9c3637bcf56faa6"}, -] - -[package.dependencies] -flake8 = "*" - -[package.extras] -test = ["pytest"] - -[[package]] -name = "flake8-copyright" -version = "0.2.4" -description = "Adds copyright checks to flake8" -optional = false -python-versions = "*" -files = [ - {file = "flake8-copyright-0.2.4.tar.gz", hash = "sha256:b78491fcf575266d7e78dcfa899c876edd1c29929d247de3408bf4e3f971bf1c"}, - {file = "flake8_copyright-0.2.4-py3-none-any.whl", hash = "sha256:5d33d900c4183bb6748692407867229d1e5b84016a100e8899a7f58dcf52223f"}, -] - -[package.dependencies] -setuptools = "*" - -[[package]] -name = "flake8-docstrings" -version = "1.7.0" -description = "Extension for flake8 which uses pydocstyle to check docstrings" -optional = false -python-versions = ">=3.7" -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"}, -] - -[package.dependencies] -flake8 = ">=3" -pydocstyle = ">=2.1" - [[package]] name = "google-auth" version = "2.31.0" @@ -921,20 +799,6 @@ qtconsole = ["qtconsole"] test = ["packaging", "pickleshare", "pytest", "pytest-asyncio (<0.22)", "testpath"] test-extra = ["curio", "ipython[test]", "matplotlib (!=3.2.0)", "nbformat", "numpy (>=1.23)", "pandas", "trio"] -[[package]] -name = "isort" -version = "5.13.2" -description = "A Python utility / library to sort Python imports." -optional = false -python-versions = ">=3.8.0" -files = [ - {file = "isort-5.13.2-py3-none-any.whl", hash = "sha256:8ca5e72a8d85860d5a3fa69b8745237f2939afe12dbf656afbcb47fe72d947a6"}, - {file = "isort-5.13.2.tar.gz", hash = "sha256:48fdfcb9face5d58a4f6dde2e72a1fb8dcaf8ab26f95ab49fab84c2ddefb0109"}, -] - -[package.extras] -colors = ["colorama (>=0.4.6)"] - [[package]] name = "jedi" version = "0.19.1" @@ -1184,17 +1048,6 @@ files = [ [package.dependencies] traitlets = "*" -[[package]] -name = "mccabe" -version = "0.7.0" -description = "McCabe checker, plugin for flake8" -optional = false -python-versions = ">=3.6" -files = [ - {file = "mccabe-0.7.0-py2.py3-none-any.whl", hash = "sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e"}, - {file = "mccabe-0.7.0.tar.gz", hash = "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325"}, -] - [[package]] name = "mypy-extensions" version = "1.0.0" @@ -1436,31 +1289,6 @@ files = [ qa = ["flake8 (==5.0.4)", "mypy (==0.971)", "types-setuptools (==67.2.0.1)"] testing = ["docopt", "pytest"] -[[package]] -name = "pathspec" -version = "0.12.1" -description = "Utility library for gitignore style pattern matching of file paths." -optional = false -python-versions = ">=3.8" -files = [ - {file = "pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08"}, - {file = "pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712"}, -] - -[[package]] -name = "pep8-naming" -version = "0.14.1" -description = "Check PEP-8 naming conventions, plugin for flake8" -optional = false -python-versions = ">=3.8" -files = [ - {file = "pep8-naming-0.14.1.tar.gz", hash = "sha256:1ef228ae80875557eb6c1549deafed4dabbf3261cfcafa12f773fe0db9be8a36"}, - {file = "pep8_naming-0.14.1-py3-none-any.whl", hash = "sha256:63f514fc777d715f935faf185dedd679ab99526a7f2f503abb61587877f7b1c5"}, -] - -[package.dependencies] -flake8 = ">=5.0.0" - [[package]] name = "pexpect" version = "4.9.0" @@ -1475,22 +1303,6 @@ files = [ [package.dependencies] ptyprocess = ">=0.5" -[[package]] -name = "platformdirs" -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" -files = [ - {file = "platformdirs-4.2.2-py3-none-any.whl", hash = "sha256:2d7a1657e36a80ea911db832a8a6ece5ee53d8de21edd5cc5879af6530b1bfee"}, - {file = "platformdirs-4.2.2.tar.gz", hash = "sha256:38b7b51f512eed9e84a22788b4bce1de17c0adb134d6becb09836e37d8654cd3"}, -] - -[package.extras] -docs = ["furo (>=2023.9.10)", "proselint (>=0.13)", "sphinx (>=7.2.6)", "sphinx-autodoc-typehints (>=1.25.2)"] -test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.4.3)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)"] -type = ["mypy (>=1.8)"] - [[package]] name = "pluggy" version = "1.5.0" @@ -1623,17 +1435,6 @@ files = [ [package.dependencies] pyasn1 = ">=0.4.6,<0.7.0" -[[package]] -name = "pycodestyle" -version = "2.11.1" -description = "Python style guide checker" -optional = false -python-versions = ">=3.8" -files = [ - {file = "pycodestyle-2.11.1-py2.py3-none-any.whl", hash = "sha256:44fe31000b2d866f2e41841b18528a505fbd7fef9017b04eff4e2648a0fadc67"}, - {file = "pycodestyle-2.11.1.tar.gz", hash = "sha256:41ba0e7afc9752dfb53ced5489e89f8186be00e599e712660695b7a75ff2663f"}, -] - [[package]] name = "pycparser" version = "2.22" @@ -1768,34 +1569,6 @@ files = [ [package.dependencies] typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0" -[[package]] -name = "pydocstyle" -version = "6.3.0" -description = "Python docstring style checker" -optional = false -python-versions = ">=3.6" -files = [ - {file = "pydocstyle-6.3.0-py3-none-any.whl", hash = "sha256:118762d452a49d6b05e194ef344a55822987a462831ade91ec5c06fd2169d019"}, - {file = "pydocstyle-6.3.0.tar.gz", hash = "sha256:7ce43f0c0ac87b07494eb9c0b462c0b73e6ff276807f204d6b53edc72b7e44e1"}, -] - -[package.dependencies] -snowballstemmer = ">=2.2.0" - -[package.extras] -toml = ["tomli (>=1.2.3)"] - -[[package]] -name = "pyflakes" -version = "3.2.0" -description = "passive checker of Python programs" -optional = false -python-versions = ">=3.8" -files = [ - {file = "pyflakes-3.2.0-py2.py3-none-any.whl", hash = "sha256:84b5be138a2dfbb40689ca07e2152deb896a65c3a3e24c251c5c62489568074a"}, - {file = "pyflakes-3.2.0.tar.gz", hash = "sha256:1c61603ff154621fb2a9172037d84dca3500def8c8b630657d1701f026f8af3f"}, -] - [[package]] name = "pygments" version = "2.18.0" @@ -1851,21 +1624,6 @@ cffi = ">=1.4.1" docs = ["sphinx (>=1.6.5)", "sphinx-rtd-theme"] tests = ["hypothesis (>=3.27.0)", "pytest (>=3.2.1,!=3.3.0)"] -[[package]] -name = "pyproject-flake8" -version = "7.0.0" -description = "pyproject-flake8 (`pflake8`), a monkey patching wrapper to connect flake8 with pyproject.toml configuration" -optional = false -python-versions = ">=3.8.1" -files = [ - {file = "pyproject_flake8-7.0.0-py3-none-any.whl", hash = "sha256:611e91b49916e6d0685f88423ad4baff490888278a258975403c0dee6eb6072e"}, - {file = "pyproject_flake8-7.0.0.tar.gz", hash = "sha256:5b953592336bc04d86e8942fdca1014256044a3445c8b6ca9467d08636749158"}, -] - -[package.dependencies] -flake8 = "7.0.0" -tomli = {version = "*", markers = "python_version < \"3.11\""} - [[package]] name = "pyrfc3339" version = "1.1" @@ -2080,7 +1838,6 @@ files = [ {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_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef"}, {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"}, @@ -2292,20 +2049,31 @@ files = [ pyasn1 = ">=0.1.3" [[package]] -name = "setuptools" -version = "70.2.0" -description = "Easily download, build, install, upgrade, and uninstall Python packages" +name = "ruff" +version = "0.4.10" +description = "An extremely fast Python linter and code formatter, written in Rust." optional = false -python-versions = ">=3.8" +python-versions = ">=3.7" files = [ - {file = "setuptools-70.2.0-py3-none-any.whl", hash = "sha256:b8b8060bb426838fbe942479c90296ce976249451118ef566a5a0b7d8b78fb05"}, - {file = "setuptools-70.2.0.tar.gz", hash = "sha256:bd63e505105011b25c3c11f753f7e3b8465ea739efddaccef8f0efac2137bac1"}, + {file = "ruff-0.4.10-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:5c2c4d0859305ac5a16310eec40e4e9a9dec5dcdfbe92697acd99624e8638dac"}, + {file = "ruff-0.4.10-py3-none-macosx_11_0_arm64.whl", hash = "sha256:a79489607d1495685cdd911a323a35871abfb7a95d4f98fc6f85e799227ac46e"}, + {file = "ruff-0.4.10-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b1dd1681dfa90a41b8376a61af05cc4dc5ff32c8f14f5fe20dba9ff5deb80cd6"}, + {file = "ruff-0.4.10-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c75c53bb79d71310dc79fb69eb4902fba804a81f374bc86a9b117a8d077a1784"}, + {file = "ruff-0.4.10-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:18238c80ee3d9100d3535d8eb15a59c4a0753b45cc55f8bf38f38d6a597b9739"}, + {file = "ruff-0.4.10-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:d8f71885bce242da344989cae08e263de29752f094233f932d4f5cfb4ef36a81"}, + {file = "ruff-0.4.10-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:330421543bd3222cdfec481e8ff3460e8702ed1e58b494cf9d9e4bf90db52b9d"}, + {file = "ruff-0.4.10-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9e9b6fb3a37b772628415b00c4fc892f97954275394ed611056a4b8a2631365e"}, + {file = "ruff-0.4.10-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0f54c481b39a762d48f64d97351048e842861c6662d63ec599f67d515cb417f6"}, + {file = "ruff-0.4.10-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:67fe086b433b965c22de0b4259ddfe6fa541c95bf418499bedb9ad5fb8d1c631"}, + {file = "ruff-0.4.10-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:acfaaab59543382085f9eb51f8e87bac26bf96b164839955f244d07125a982ef"}, + {file = "ruff-0.4.10-py3-none-musllinux_1_2_i686.whl", hash = "sha256:3cea07079962b2941244191569cf3a05541477286f5cafea638cd3aa94b56815"}, + {file = "ruff-0.4.10-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:338a64ef0748f8c3a80d7f05785930f7965d71ca260904a9321d13be24b79695"}, + {file = "ruff-0.4.10-py3-none-win32.whl", hash = "sha256:ffe3cd2f89cb54561c62e5fa20e8f182c0a444934bf430515a4b422f1ab7b7ca"}, + {file = "ruff-0.4.10-py3-none-win_amd64.whl", hash = "sha256:67f67cef43c55ffc8cc59e8e0b97e9e60b4837c8f21e8ab5ffd5d66e196e25f7"}, + {file = "ruff-0.4.10-py3-none-win_arm64.whl", hash = "sha256:dd1fcee327c20addac7916ca4e2653fbbf2e8388d8a6477ce5b4e986b68ae6c0"}, + {file = "ruff-0.4.10.tar.gz", hash = "sha256:3aa4f2bc388a30d346c56524f7cacca85945ba124945fe489952aadb6b5cd804"}, ] -[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)", "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.16.0" @@ -2328,17 +2096,6 @@ files = [ {file = "sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc"}, ] -[[package]] -name = "snowballstemmer" -version = "2.2.0" -description = "This package provides 29 stemmers for 28 languages generated from Snowball algorithms." -optional = false -python-versions = "*" -files = [ - {file = "snowballstemmer-2.2.0-py2.py3-none-any.whl", hash = "sha256:c8e1716e83cc398ae16824e5572ae04e0d9fc2c6b985fb0f900f5f0c96ecba1a"}, - {file = "snowballstemmer-2.2.0.tar.gz", hash = "sha256:09b16deb8547d3412ad7b590689584cd0fe25ec8db3be37788be3810cbf19cb1"}, -] - [[package]] name = "stack-data" version = "0.6.3" @@ -2658,4 +2415,4 @@ test = ["big-O", "importlib-resources", "jaraco.functools", "jaraco.itertools", [metadata] lock-version = "2.0" python-versions = "^3.10" -content-hash = "dec2c219f484ffed3b0463e3fb2463be38e7fcf95c94a4b8637a77ccb48aadc2" +content-hash = "8465c5478419b55eb44cb47e69e37f7495fa46c4b7a143d4424f55bc70c2845d" diff --git a/pyproject.toml b/pyproject.toml index ddeeb3a8f..421bc01f6 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -35,21 +35,13 @@ jsonschema = "*" optional = true [tool.poetry.group.format.dependencies] -black = "^24.4.2" -isort = "^5.13.2" +ruff = "^0.4.5" [tool.poetry.group.lint] optional = true [tool.poetry.group.lint.dependencies] -black = "^24.4.2" -isort = "^5.13.2" -flake8 = "^7.0.0" -flake8-docstrings = "^1.7.0" -flake8-copyright = "^0.2.4" -flake8-builtins = "^2.5.0" -pyproject-flake8 = "^7.0.0" -pep8-naming = "^0.14.1" +ruff = "^0.4.5" codespell = "^2.3.0" [tool.poetry.group.unit.dependencies] @@ -85,35 +77,40 @@ log_cli_level = "INFO" markers = ["unstable"] # Formatting tools configuration -[tool.black] +[tool.ruff] +# preview and explicit preview are enabled for CPY001 +preview = true +target-version = "py38" +src = ["src", "."] line-length = 99 -target-version = ["py38"] -[tool.isort] -profile = "black" -known_third_party = "mysql.connector" - -# Linting tools configuration -[tool.flake8] -max-line-length = 99 -max-doc-length = 99 -max-complexity = 10 -exclude = [".git", "__pycache__", ".tox", "build", "dist", "*.egg_info", "venv"] -select = ["E", "W", "F", "C", "N", "R", "D", "H"] -# Ignore W503, E501 because using black creates errors with this -# Ignore D107 Missing docstring in __init__ -# Ignore D105 Missing docstring in magic method -# Ignore D415 Docstring first line punctuation (doesn't make sense for properties) -# Ignore D403 First word of the first line should be properly capitalized (false positive on "MySQL") -# Ignore N818 Exception should be named with an Error suffix -# Ignore D102 Missing docstring in public method (pydocstyle doesn't look for docstrings in super class -# Ignore W505 So that strings in comments aren't split across lines -# https://github.com/PyCQA/pydocstyle/issues/309) TODO: add pylint check? https://github.com/PyCQA/pydocstyle/issues/309#issuecomment-1284142716 -ignore = ["W503", "E501", "D107", "D105", "D415", "D403", "N818", "D102", "W505"] +[tool.ruff.lint] +explicit-preview-rules = true +select = ["A", "E", "W", "F", "C", "N", "D", "I", "CPY001"] +ignore = [ + # Missing docstring in public method (pydocstyle doesn't look for docstrings in super class + # https://github.com/PyCQA/pydocstyle/issues/309) TODO: add pylint check? https://github.com/PyCQA/pydocstyle/issues/309#issuecomment-1284142716 + "D102", + "D105", # Missing docstring in magic method + "D107", # Missing docstring in __init__ + "D403", # First word of the first line should be capitalized (false positive on "MySQL") + "D415", # Docstring first line punctuation (doesn't make sense for properties) + "E501", # Line too long (because using black creates errors with this) + "N818", # Exception name should be named with an Error suffix + "W505", # Doc line too long (so that strings in comments aren't split across lines) +] + +[tool.ruff.lint.per-file-ignores] # D100, D101, D102, D103: Ignore missing docstrings in tests -per-file-ignores = ["tests/*:D100,D101,D102,D103,D104"] -docstring-convention = "google" +"tests/*" = ["D1"] + +[tool.ruff.lint.flake8-copyright] # Check for properly formatted copyright header in each file -copyright-check = "True" -copyright-author = "Canonical Ltd." -copyright-regexp = "Copyright\\s\\d{4}([-,]\\d{4})*\\s+%(author)s" +author = "Canonical Ltd." +notice-rgx = "Copyright\\s\\d{4}([-,]\\d{4})*\\s+" + +[tool.ruff.lint.mccabe] +max-complexity = 10 + +[tool.ruff.lint.pydocstyle] +convention = "google" diff --git a/src/container.py b/src/container.py index 099a7d753..1ad75d3b8 100644 --- a/src/container.py +++ b/src/container.py @@ -177,7 +177,7 @@ def _run_command( command: typing.List[str], *, timeout: typing.Optional[int], - input: str = None, + input: str = None, # noqa: A002 Match subprocess.run() ) -> str: """Run command in container. diff --git a/src/lifecycle.py b/src/lifecycle.py index c8ec9da46..537cec155 100644 --- a/src/lifecycle.py +++ b/src/lifecycle.py @@ -5,6 +5,7 @@ https://juju.is/docs/sdk/a-charms-life """ + import enum import logging import typing diff --git a/src/mysql_shell/__init__.py b/src/mysql_shell/__init__.py index 82fa2639e..be3c87325 100644 --- a/src/mysql_shell/__init__.py +++ b/src/mysql_shell/__init__.py @@ -82,14 +82,12 @@ def render(connection_info: "relations.database_requires.ConnectionInformation") error_file = self._container.path("/tmp/mysqlsh_error.json") temporary_script_file.write_text(script) try: - self._container.run_mysql_shell( - [ - "--no-wizard", - "--python", - "--file", - str(temporary_script_file.relative_to_container), - ] - ) + self._container.run_mysql_shell([ + "--no-wizard", + "--python", + "--file", + str(temporary_script_file.relative_to_container), + ]) except container.CalledProcessError as e: logger.exception( f"Failed to run MySQL Shell script:\n{logged_script}\n\nstderr:\n{e.stderr}\n" @@ -105,8 +103,8 @@ def render(connection_info: "relations.database_requires.ConnectionInformation") raise ShellDBError(**exception) except ShellDBError as e: if e.code == 2003: - logger.exception(server_exceptions.ConnectionError.MESSAGE) - raise server_exceptions.ConnectionError + logger.exception(server_exceptions.ConnectionError_.MESSAGE) + raise server_exceptions.ConnectionError_ else: logger.exception( f"Failed to run MySQL Shell script:\n{logged_script}\n\nMySQL client error {e.code}\nMySQL Shell traceback:\n{e.traceback_message}\n" @@ -136,13 +134,11 @@ def create_application_database_and_user(self, *, username: str, database: str) attributes = self._get_attributes() logger.debug(f"Creating {database=} and {username=} with {attributes=}") password = utils.generate_password() - self._run_sql( - [ - f"CREATE DATABASE IF NOT EXISTS `{database}`", - f"CREATE USER `{username}` IDENTIFIED BY '{password}' ATTRIBUTE '{attributes}'", - f"GRANT ALL PRIVILEGES ON `{database}`.* TO `{username}`", - ] - ) + self._run_sql([ + f"CREATE DATABASE IF NOT EXISTS `{database}`", + f"CREATE USER `{username}` IDENTIFIED BY '{password}' ATTRIBUTE '{attributes}'", + f"GRANT ALL PRIVILEGES ON `{database}`.* TO `{username}`", + ]) logger.debug(f"Created {database=} and {username=} with {attributes=}") return password @@ -150,9 +146,10 @@ def add_attributes_to_mysql_router_user( self, *, username: str, router_id: str, unit_name: str ) -> None: """Add attributes to user created during MySQL Router bootstrap.""" - attributes = self._get_attributes( - {"router_id": router_id, "created_by_juju_unit": unit_name} - ) + attributes = self._get_attributes({ + "router_id": router_id, + "created_by_juju_unit": unit_name, + }) logger.debug(f"Adding {attributes=} to {username=}") self._run_sql([f"ALTER USER `{username}` ATTRIBUTE '{attributes}'"]) logger.debug(f"Added {attributes=} to {username=}") diff --git a/src/relations/cos.py b/src/relations/cos.py index a07f012c9..494cd4fe1 100644 --- a/src/relations/cos.py +++ b/src/relations/cos.py @@ -2,6 +2,7 @@ # See LICENSE file for licensing details. """Relation to the cos charms.""" + import logging import typing from dataclasses import dataclass diff --git a/src/rock.py b/src/rock.py index e2d569098..e0063ef9b 100644 --- a/src/rock.py +++ b/src/rock.py @@ -116,20 +116,18 @@ def update_mysql_router_service(self, *, enabled: bool, tls: bool = None) -> Non startup = ops.pebble.ServiceStartup.ENABLED.value else: startup = ops.pebble.ServiceStartup.DISABLED.value - layer = ops.pebble.Layer( - { - "services": { - self._SERVICE_NAME: { - "override": "replace", - "summary": "MySQL Router", - "command": command, - "startup": startup, - "user": _UNIX_USERNAME, - "group": _UNIX_USERNAME, - }, + layer = ops.pebble.Layer({ + "services": { + self._SERVICE_NAME: { + "override": "replace", + "summary": "MySQL Router", + "command": command, + "startup": startup, + "user": _UNIX_USERNAME, + "group": _UNIX_USERNAME, }, - } - ) + }, + }) self._container.add_layer(self._SERVICE_NAME, layer, combine=True) # `self._container.replan()` does not stop services that have been disabled # Use `restart()` and `stop()` instead @@ -168,32 +166,28 @@ def update_mysql_router_exporter_service( "MYSQLROUTER_EXPORTER_SERVICE_NAME": self._unit_name.replace("/", "-"), } if tls: - environment.update( - { - "MYSQLROUTER_TLS_CACERT_PATH": certificate_authority_filename, - "MYSQLROUTER_TLS_CERT_PATH": certificate_filename, - "MYSQLROUTER_TLS_KEY_PATH": key_filename, - } - ) + environment.update({ + "MYSQLROUTER_TLS_CACERT_PATH": certificate_authority_filename, + "MYSQLROUTER_TLS_CERT_PATH": certificate_filename, + "MYSQLROUTER_TLS_KEY_PATH": key_filename, + }) else: startup = ops.pebble.ServiceStartup.DISABLED.value environment = {} - layer = ops.pebble.Layer( - { - "services": { - self._EXPORTER_SERVICE_NAME: { - "override": "replace", - "summary": "MySQL Router Exporter", - "command": "/start-mysql-router-exporter.sh", - "startup": startup, - "user": _UNIX_USERNAME, - "group": _UNIX_USERNAME, - "environment": environment, - }, + layer = ops.pebble.Layer({ + "services": { + self._EXPORTER_SERVICE_NAME: { + "override": "replace", + "summary": "MySQL Router Exporter", + "command": "/start-mysql-router-exporter.sh", + "startup": startup, + "user": _UNIX_USERNAME, + "group": _UNIX_USERNAME, + "environment": environment, }, - } - ) + }, + }) self._container.add_layer(self._EXPORTER_SERVICE_NAME, layer, combine=True) # `self._container.replan()` does not stop services that have been disabled # Use `restart()` and `stop()` instead @@ -216,20 +210,18 @@ def update_logrotate_executor_service(self, *, enabled: bool) -> None: if enabled else ops.pebble.ServiceStartup.DISABLED.value ) - layer = ops.pebble.Layer( - { - "services": { - self._LOGROTATE_EXECUTOR_SERVICE_NAME: { - "override": "replace", - "summary": "Logrotate executor", - "command": "python3 /logrotate_executor.py", - "startup": startup, - "user": _UNIX_USERNAME, - "group": _UNIX_USERNAME, - }, + layer = ops.pebble.Layer({ + "services": { + self._LOGROTATE_EXECUTOR_SERVICE_NAME: { + "override": "replace", + "summary": "Logrotate executor", + "command": "python3 /logrotate_executor.py", + "startup": startup, + "user": _UNIX_USERNAME, + "group": _UNIX_USERNAME, }, - } - ) + }, + }) self._container.add_layer(self._LOGROTATE_EXECUTOR_SERVICE_NAME, layer, combine=True) # `self._container.replan()` does not stop services that have been disabled # Use `restart()` and `stop()` instead @@ -240,7 +232,11 @@ def update_logrotate_executor_service(self, *, enabled: bool) -> None: # TODO python3.10 min version: Use `list` instead of `typing.List` def _run_command( - self, command: typing.List[str], *, timeout: typing.Optional[int], input: str = None + self, + command: typing.List[str], + *, + timeout: typing.Optional[int], + input: str = None, # noqa: A002 Match subprocess.run() ) -> str: try: process = self._container.exec( diff --git a/src/server_exceptions.py b/src/server_exceptions.py index 82fc47080..043908e37 100644 --- a/src/server_exceptions.py +++ b/src/server_exceptions.py @@ -12,7 +12,7 @@ class Error(status_exception.StatusException): """MySQL Server unreachable or unhealthy""" -class ConnectionError(Error): +class ConnectionError_(Error): # noqa: N801 for underscore in name """MySQL Server unreachable MySQL client error 2003 diff --git a/src/workload.py b/src/workload.py index e26a26c7b..33131e7bd 100644 --- a/src/workload.py +++ b/src/workload.py @@ -291,8 +291,8 @@ def _bootstrap_router(self, *, event, tls: bool) -> None: elif match := re.fullmatch(r"Error:.*\((?P2[0-9]{3})\)", stderr): code = int(match.group("code")) if code == 2003: - logger.error(server_exceptions.ConnectionError.MESSAGE) - raise server_exceptions.ConnectionError from None + logger.error(server_exceptions.ConnectionError_.MESSAGE) + raise server_exceptions.ConnectionError_ from None else: logger.error(f"Bootstrap failed with MySQL client error {code}") raise Exception("Failed to bootstrap router") from None diff --git a/tests/integration/helpers.py b/tests/integration/helpers.py index 9c9f2eadd..a4b885445 100644 --- a/tests/integration/helpers.py +++ b/tests/integration/helpers.py @@ -157,7 +157,7 @@ async def delete_file_or_directory_in_unit( if path.strip() in ["/", "."]: return - return_code, _, _ = await ops_test.juju( + await ops_test.juju( "ssh", "--container", container_name, @@ -274,7 +274,7 @@ async def ls_la_in_unit( Args: ops_test: The ops test framework unit_name: The name of unit in which to run ls -la - path: The path from which to run ls -la + directory: The directory from which to run ls -la container_name: The container where to run ls -la Returns: @@ -592,7 +592,7 @@ async def ensure_all_units_continuous_writes_incrementing( select_all_continuous_writes_sql, ) ) - numbers = {n for n in range(1, max_written_value)} + numbers = set(range(1, max_written_value)) assert ( numbers <= all_written_values ), f"Missing numbers in database for unit {unit.name}" diff --git a/tests/integration/test_log_rotation.py b/tests/integration/test_log_rotation.py index 52f69d082..5690aee87 100644 --- a/tests/integration/test_log_rotation.py +++ b/tests/integration/test_log_rotation.py @@ -140,9 +140,10 @@ async def test_log_rotation(ops_test: OpsTest): len(ls_la_output) == 2 ), f"❌ unexpected files/directories in log directory: {ls_la_output}" directories = [line.split()[-1] for line in ls_la_output] - assert sorted(directories) == sorted( - ["mysqlrouter.log", "archive_mysqlrouter"] - ), f"❌ unexpected files/directories in log directory: {ls_la_output}" + assert sorted(directories) == sorted([ + "mysqlrouter.log", + "archive_mysqlrouter", + ]), f"❌ unexpected files/directories in log directory: {ls_la_output}" logger.info("Ensuring log files was rotated") file_contents = await read_contents_from_file_in_unit( diff --git a/tests/integration/test_node_port.py b/tests/integration/test_node_port.py index f6529bfaf..4e454137f 100644 --- a/tests/integration/test_node_port.py +++ b/tests/integration/test_node_port.py @@ -101,12 +101,16 @@ async def test_build_and_deploy(ops_test: OpsTest): async with ops_test.fast_forward(): logger.info("Relating mysql, mysqlrouter and application") - await ops_test.model.relate( - f"{MYSQL_APP_NAME}", f"{SELF_SIGNED_CERTIFICATE_NAME}:certificates" - ), - await ops_test.model.relate( - f"{MYSQL_ROUTER_APP_NAME}", f"{SELF_SIGNED_CERTIFICATE_NAME}:certificates" - ), + ( + await ops_test.model.relate( + f"{MYSQL_APP_NAME}", f"{SELF_SIGNED_CERTIFICATE_NAME}:certificates" + ), + ) + ( + await ops_test.model.relate( + f"{MYSQL_ROUTER_APP_NAME}", f"{SELF_SIGNED_CERTIFICATE_NAME}:certificates" + ), + ) # Relate the database with mysqlrouter await ops_test.model.relate( @@ -173,13 +177,11 @@ async def test_node_port_and_clusterip_setup(): for app_name in [DATA_INTEGRATOR, APPLICATION_APP_NAME]: try: relation_info = yaml.safe_load( - subprocess.check_output( - [ - "juju", - "show-unit", - f"{app_name}/0", - ] - ) + subprocess.check_output([ + "juju", + "show-unit", + f"{app_name}/0", + ]) )[f"{app_name}/0"]["relation-info"] if app_name == DATA_INTEGRATOR: endpoint = list(filter(lambda x: x["endpoint"] == "mysql", relation_info))[0][ diff --git a/tests/unit/conftest.py b/tests/unit/conftest.py index 59c278ce5..abeb980eb 100644 --- a/tests/unit/conftest.py +++ b/tests/unit/conftest.py @@ -46,7 +46,8 @@ def patch(monkeypatch): def kubernetes_patch(monkeypatch): monkeypatch.setattr("kubernetes_charm.KubernetesRouterCharm.model_service_domain", "") monkeypatch.setattr( - "rock.Rock._run_command", lambda *args, **kwargs: "null" # Use "null" for `json.loads()` + "rock.Rock._run_command", + lambda *args, **kwargs: "null", # Use "null" for `json.loads()` ) monkeypatch.setattr("rock._Path.read_text", lambda *args, **kwargs: "") monkeypatch.setattr("rock._Path.write_text", lambda *args, **kwargs: None) diff --git a/tests/unit/scenario_/database_relations/combinations.py b/tests/unit/scenario_/database_relations/combinations.py index b474970cb..93f8a630e 100644 --- a/tests/unit/scenario_/database_relations/combinations.py +++ b/tests/unit/scenario_/database_relations/combinations.py @@ -17,12 +17,10 @@ def _relation_combinations( for number_of_relations in relation_amounts: for combination in itertools.combinations_with_replacement(relations, number_of_relations): combination: tuple[scenario.Relation] - combinations.append( - [ - relation.replace(relation_id=scenario.state.next_relation_id()) - for relation in combination - ] - ) + combinations.append([ + relation.replace(relation_id=scenario.state.next_relation_id()) + for relation in combination + ]) return combinations diff --git a/tests/unit/scenario_/database_relations/test_database_relations.py b/tests/unit/scenario_/database_relations/test_database_relations.py index 3d7ed5e9c..6614e428e 100644 --- a/tests/unit/scenario_/database_relations/test_database_relations.py +++ b/tests/unit/scenario_/database_relations/test_database_relations.py @@ -38,13 +38,11 @@ def output_states(*, relations: list[scenario.Relation]) -> typing.Iterable[scen ) events = [container.pebble_ready_event] for relation in relations: - events.extend( - ( - relation.created_event, - # data_interfaces lib does not always emit event (to charm) on *-relation-changed - # relation.changed_event, - ) - ) + events.extend(( + relation.created_event, + # data_interfaces lib does not always emit event (to charm) on *-relation-changed + # relation.changed_event, + )) for event in events: output = context.run(event, input_state) output.relations.pop() # Remove PeerRelation diff --git a/tox.ini b/tox.ini index 4f89db787..04e049073 100644 --- a/tox.ini +++ b/tox.ini @@ -50,8 +50,8 @@ commands_pre = poetry install --only format commands = poetry lock --no-update - poetry run isort {[vars]all_path} - poetry run black {[vars]all_path} + poetry run ruff check --fix {[vars]all_path} + poetry run ruff format {[vars]all_path} [testenv:lint] description = Check code against coding style standards @@ -60,10 +60,8 @@ commands_pre = commands = poetry check --lock poetry run codespell {[vars]all_path} - # pflake8 wrapper supports config from pyproject.toml - poetry run pflake8 {[vars]all_path} - poetry run isort --check-only --diff {[vars]all_path} - poetry run black --check --diff {[vars]all_path} + poetry run ruff check {[vars]all_path} + poetry run ruff format --check --diff {[vars]all_path} [testenv:unit] description = Run unit tests