From b0de74537c8eafc8e608b7bf6c138975d622acb5 Mon Sep 17 00:00:00 2001 From: lgcorzo Date: Tue, 28 Apr 2026 21:05:07 +0200 Subject: [PATCH 1/3] security: solve remaining active vulnerabilities by updating build tools and mlflow --- Dockerfile | 2 +- poetry.lock | 407 ++++++++++++++++++++++++++++++++++++++++++----- pyproject.toml | 7 +- requirements.txt | 33 ---- 4 files changed, 368 insertions(+), 81 deletions(-) diff --git a/Dockerfile b/Dockerfile index f2c0967..f05b365 100644 --- a/Dockerfile +++ b/Dockerfile @@ -4,7 +4,7 @@ FROM python:3.12-slim AS builder WORKDIR /build # Install Poetry and export plugin -RUN pip install poetry==1.8.3 +RUN pip install poetry==2.0.1 # Copy dependency files COPY pyproject.toml poetry.lock README.md ./ diff --git a/poetry.lock b/poetry.lock index 8923404..ecf3568 100644 --- a/poetry.lock +++ b/poetry.lock @@ -291,7 +291,7 @@ version = "0.0.4" description = "Document parameters, class attributes, return types, and variables inline, with Annotated." optional = false python-versions = ">=3.8" -groups = ["main"] +groups = ["main", "dev"] files = [ {file = "annotated_doc-0.0.4-py3-none-any.whl", hash = "sha256:571ac1dc6991c450b25a9c2d84a3705e2ae7a53467b5d111c24fa8baabbed320"}, {file = "annotated_doc-0.0.4.tar.gz", hash = "sha256:fbcda96e87e9c92ad167c2e53839e57503ecfda18804ea28102353485033faa4"}, @@ -303,7 +303,7 @@ version = "0.7.0" description = "Reusable constraint types to use with typing.Annotated" optional = false python-versions = ">=3.8" -groups = ["main", "checks"] +groups = ["main", "checks", "dev"] files = [ {file = "annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53"}, {file = "annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89"}, @@ -326,7 +326,7 @@ version = "4.13.0" description = "High-level concurrency and networking framework on top of asyncio or Trio" optional = false python-versions = ">=3.10" -groups = ["main"] +groups = ["main", "dev"] files = [ {file = "anyio-4.13.0-py3-none-any.whl", hash = "sha256:08b310f9e24a9594186fd75b4f73f4a4152069e3853f1ed8bfbf58369f4ad708"}, {file = "anyio-4.13.0.tar.gz", hash = "sha256:334b70e641fd2221c1505b3890c69882fe4a2df910cba14d97019b90b24439dc"}, @@ -471,6 +471,22 @@ files = [ {file = "attrs-26.1.0.tar.gz", hash = "sha256:d03ceb89cb322a8fd706d4fb91940737b6642aa36998fe130a9bc96c985eff32"}, ] +[[package]] +name = "authlib" +version = "1.7.0" +description = "The ultimate Python library in building OAuth and OpenID Connect servers and clients." +optional = false +python-versions = ">=3.10" +groups = ["dev"] +files = [ + {file = "authlib-1.7.0-py2.py3-none-any.whl", hash = "sha256:e36817afb02f6f0b6bf55f150782499ddd6ddf44b402bb055d3263cc65ac9ae0"}, + {file = "authlib-1.7.0.tar.gz", hash = "sha256:b3e326c9aa9cc3ea95fe7d89fd880722d3608da4d00e8a27e061e64b48d801d5"}, +] + +[package.dependencies] +cryptography = "*" +joserfc = ">=1.6.0" + [[package]] name = "bandit" version = "1.9.4" @@ -758,7 +774,7 @@ version = "2.0.0" description = "Foreign Function Interface for Python calling C code." optional = false python-versions = ">=3.9" -groups = ["main", "notebooks"] +groups = ["main", "dev", "notebooks"] files = [ {file = "cffi-2.0.0-cp310-cp310-macosx_10_13_x86_64.whl", hash = "sha256:0cf2d91ecc3fcc0625c2c530fe004f82c110405f101548512cce44322fa8ac44"}, {file = "cffi-2.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f73b96c41e3b2adedc34a7356e64c8eb96e03a3782b535e043a986276ce12a49"}, @@ -845,7 +861,7 @@ files = [ {file = "cffi-2.0.0-cp39-cp39-win_amd64.whl", hash = "sha256:b882b3df248017dba09d6b16defe9b5c407fe32fc7c65a9c69798e6175601be9"}, {file = "cffi-2.0.0.tar.gz", hash = "sha256:44d1b5909021139fe36001ae048dbdde8214afa20200eda0f64c068cac5d5529"}, ] -markers = {notebooks = "implementation_name == \"pypy\""} +markers = {dev = "platform_python_implementation != \"PyPy\"", notebooks = "implementation_name == \"pypy\""} [package.dependencies] pycparser = {version = "*", markers = "implementation_name != \"PyPy\""} @@ -1007,7 +1023,7 @@ version = "8.3.3" description = "Composable command line interface toolkit" optional = false python-versions = ">=3.10" -groups = ["main"] +groups = ["main", "dev"] files = [ {file = "click-8.3.3-py3-none-any.whl", hash = "sha256:a2bf429bb3033c89fa4936ffb35d5cb471e3719e1f3c8a7c3fff0b8314305613"}, {file = "click-8.3.3.tar.gz", hash = "sha256:398329ad4837b2ff7cbe1dd166a4c0f8900c3ca3a218de04466f38f6497f18a2"}, @@ -1086,12 +1102,12 @@ 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", "checks", "commits", "notebooks"] +groups = ["main", "checks", "commits", "dev", "notebooks"] 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 = {checks = "platform_system == \"Windows\" or sys_platform == \"win32\"", notebooks = "sys_platform == \"win32\""} +markers = {checks = "platform_system == \"Windows\" or sys_platform == \"win32\"", dev = "platform_system == \"Windows\"", notebooks = "sys_platform == \"win32\""} [[package]] name = "comm" @@ -1421,7 +1437,7 @@ version = "46.0.7" description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." optional = false python-versions = "!=3.9.0,!=3.9.1,>=3.8" -groups = ["main"] +groups = ["main", "dev"] files = [ {file = "cryptography-46.0.7-cp311-abi3-macosx_10_9_universal2.whl", hash = "sha256:ea42cbe97209df307fdc3b155f1b6fa2577c0defa8f1f7d3be7d31d189108ad4"}, {file = "cryptography-46.0.7-cp311-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:b36a4695e29fe69215d75960b22577197aca3f7a25b9cf9d165dcfe9d80bc325"}, @@ -1720,6 +1736,27 @@ docs = ["myst-parser (==0.18.0)", "sphinx (==5.1.1)"] ssh = ["paramiko (>=2.4.3)"] websockets = ["websocket-client (>=1.3.0)"] +[[package]] +name = "dparse" +version = "0.6.4" +description = "A parser for Python dependency files" +optional = false +python-versions = ">=3.7" +groups = ["dev"] +files = [ + {file = "dparse-0.6.4-py3-none-any.whl", hash = "sha256:fbab4d50d54d0e739fbb4dedfc3d92771003a5b9aa8545ca7a7045e3b174af57"}, + {file = "dparse-0.6.4.tar.gz", hash = "sha256:90b29c39e3edc36c6284c82c4132648eaf28a01863eb3c231c2512196132201a"}, +] + +[package.dependencies] +packaging = "*" + +[package.extras] +all = ["pipenv", "poetry", "pyyaml"] +conda = ["pyyaml"] +pipenv = ["pipenv"] +poetry = ["poetry"] + [[package]] name = "dpath" version = "2.2.0" @@ -2942,12 +2979,59 @@ 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"] +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"}, ] +[[package]] +name = "httpcore" +version = "1.0.9" +description = "A minimal low-level HTTP client." +optional = false +python-versions = ">=3.8" +groups = ["dev"] +files = [ + {file = "httpcore-1.0.9-py3-none-any.whl", hash = "sha256:2d400746a40668fc9dec9810239072b40b4484b640a8c38fd654a024c7a1bf55"}, + {file = "httpcore-1.0.9.tar.gz", hash = "sha256:6e34463af53fd2ab5d807f399a9b45ea31c3dfa2276f15a2c3f00afff6e176e8"}, +] + +[package.dependencies] +certifi = "*" +h11 = ">=0.16" + +[package.extras] +asyncio = ["anyio (>=4.0,<5.0)"] +http2 = ["h2 (>=3,<5)"] +socks = ["socksio (==1.*)"] +trio = ["trio (>=0.22.0,<1.0)"] + +[[package]] +name = "httpx" +version = "0.28.1" +description = "The next generation HTTP client." +optional = false +python-versions = ">=3.8" +groups = ["dev"] +files = [ + {file = "httpx-0.28.1-py3-none-any.whl", hash = "sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad"}, + {file = "httpx-0.28.1.tar.gz", hash = "sha256:75e98c5f16b0f35b567856f597f06ff2270a374470a5c2392242528e3e3e42fc"}, +] + +[package.dependencies] +anyio = "*" +certifi = "*" +httpcore = "==1.*" +idna = "*" + +[package.extras] +brotli = ["brotli ; platform_python_implementation == \"CPython\"", "brotlicffi ; platform_python_implementation != \"CPython\""] +cli = ["click (==8.*)", "pygments (==2.*)", "rich (>=10,<14)"] +http2 = ["h2 (>=3,<5)"] +socks = ["socksio (==1.*)"] +zstd = ["zstandard (>=0.18.0)"] + [[package]] name = "huey" version = "2.6.0" @@ -3219,7 +3303,7 @@ version = "3.1.6" description = "A very fast and expressive template engine." optional = false python-versions = ">=3.7" -groups = ["main", "commits", "docs"] +groups = ["main", "commits", "dev", "docs"] files = [ {file = "jinja2-3.1.6-py3-none-any.whl", hash = "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67"}, {file = "jinja2-3.1.6.tar.gz", hash = "sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d"}, @@ -3237,12 +3321,30 @@ version = "1.5.3" description = "Lightweight pipelining with Python functions" optional = false python-versions = ">=3.9" -groups = ["main"] +groups = ["main", "dev"] files = [ {file = "joblib-1.5.3-py3-none-any.whl", hash = "sha256:5fc3c5039fc5ca8c0276333a188bbd59d6b7ab37fe6632daa76bc7f9ec18e713"}, {file = "joblib-1.5.3.tar.gz", hash = "sha256:8561a3269e6801106863fd0d6d84bb737be9e7631e33aaed3fb9ce5953688da3"}, ] +[[package]] +name = "joserfc" +version = "1.6.4" +description = "The ultimate Python library for JOSE RFCs, including JWS, JWE, JWK, JWA, JWT" +optional = false +python-versions = ">=3.9" +groups = ["dev"] +files = [ + {file = "joserfc-1.6.4-py3-none-any.whl", hash = "sha256:3e4a22b509b41908989237a045e25c8308d5fd47ab96bdae2dd8057c6451003a"}, + {file = "joserfc-1.6.4.tar.gz", hash = "sha256:34ce5f499bfcc5e9ad4cc75077f9278ab3227b71da9aaf28f9ab705f8a560d3c"}, +] + +[package.dependencies] +cryptography = ">=45.0.1" + +[package.extras] +drafts = ["pycryptodome"] + [[package]] name = "jsonschema" version = "4.26.0" @@ -3710,7 +3812,7 @@ version = "3.0.3" description = "Safely add untrusted strings to HTML/XML markup." optional = false python-versions = ">=3.9" -groups = ["main", "commits", "docs"] +groups = ["main", "commits", "dev", "docs"] files = [ {file = "markupsafe-3.0.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2f981d352f04553a7171b8e44369f2af4055f888dfb147d55e42d29e29e74559"}, {file = "markupsafe-3.0.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e1c1493fb6e50ab01d20a22826e57520f1284df32f2d8601fdd90b6304601419"}, @@ -3803,6 +3905,18 @@ files = [ {file = "markupsafe-3.0.3.tar.gz", hash = "sha256:722695808f4b6457b320fdc131280796bdceb04ab50fe1795cd540799ebe1698"}, ] +[[package]] +name = "marshmallow" +version = "4.3.0" +description = "A lightweight library for converting complex datatypes to and from native Python datatypes." +optional = false +python-versions = ">=3.10" +groups = ["dev"] +files = [ + {file = "marshmallow-4.3.0-py3-none-any.whl", hash = "sha256:46c4fe6984707e3cbd485dfebbf0a59874f58d695aad05c1668d15e8c6e13b46"}, + {file = "marshmallow-4.3.0.tar.gz", hash = "sha256:fb43c53b3fe240b8f6af37223d6ef1636f927ad9bea8ab323afad95dff090880"}, +] + [[package]] name = "matplotlib" version = "3.10.9" @@ -4465,6 +4579,32 @@ release = ["build (>=0.10)", "changelist (==0.5)", "twine (>=4.0)", "wheel (>=0. test = ["pytest (>=7.2)", "pytest-cov (>=4.0)", "pytest-xdist (>=3.0)"] test-extras = ["pytest-mpl", "pytest-randomly"] +[[package]] +name = "nltk" +version = "3.9.4" +description = "Natural Language Toolkit" +optional = false +python-versions = ">=3.10" +groups = ["dev"] +files = [ + {file = "nltk-3.9.4-py3-none-any.whl", hash = "sha256:f2fa301c3a12718ce4a0e9305c5675299da5ad9e26068218b69d692fda84828f"}, + {file = "nltk-3.9.4.tar.gz", hash = "sha256:ed03bc098a40481310320808b2db712d95d13ca65b27372f8a403949c8b523d0"}, +] + +[package.dependencies] +click = "*" +joblib = "*" +regex = ">=2021.8.3" +tqdm = "*" + +[package.extras] +all = ["matplotlib", "numpy", "pyparsing", "python-crfsuite", "requests", "scikit-learn", "scipy", "twython"] +corenlp = ["requests"] +machine-learning = ["numpy", "python-crfsuite", "scikit-learn", "scipy"] +plot = ["matplotlib"] +tgrep = ["pyparsing"] +twitter = ["twython"] + [[package]] name = "nodeenv" version = "1.10.0" @@ -5789,12 +5929,12 @@ version = "3.0" description = "C parser in Python" optional = false python-versions = ">=3.10" -groups = ["main", "notebooks"] +groups = ["main", "dev", "notebooks"] files = [ {file = "pycparser-3.0-py3-none-any.whl", hash = "sha256:b727414169a36b7d524c1c3e31839a521725078d7b2ff038656844266160a992"}, {file = "pycparser-3.0.tar.gz", hash = "sha256:600f49d217304a5902ac3c37e1281c9fe94e4d0489de643a9504c5cdfdfc6b29"}, ] -markers = {main = "implementation_name != \"PyPy\"", notebooks = "implementation_name == \"pypy\""} +markers = {main = "implementation_name != \"PyPy\"", dev = "platform_python_implementation != \"PyPy\" and implementation_name != \"PyPy\"", notebooks = "implementation_name == \"pypy\""} [[package]] name = "pydantic" @@ -5802,7 +5942,7 @@ version = "2.13.3" description = "Data validation using Python type hints" optional = false python-versions = ">=3.9" -groups = ["main", "checks"] +groups = ["main", "checks", "dev"] files = [ {file = "pydantic-2.13.3-py3-none-any.whl", hash = "sha256:6db14ac8dfc9a1e57f87ea2c0de670c251240f43cb0c30a5130e9720dc612927"}, {file = "pydantic-2.13.3.tar.gz", hash = "sha256:af09e9d1d09f4e7fe37145c1f577e1d61ceb9a41924bf0094a36506285d0a84d"}, @@ -5824,7 +5964,7 @@ version = "2.46.3" description = "Core functionality for Pydantic validation and serialization" optional = false python-versions = ">=3.9" -groups = ["main", "checks"] +groups = ["main", "checks", "dev"] files = [ {file = "pydantic_core-2.46.3-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:1da3786b8018e60349680720158cc19161cc3b4bdd815beb0a321cd5ce1ad5b1"}, {file = "pydantic_core-2.46.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:cc0988cb29d21bf4a9d5cf2ef970b5c0e38d8d8e107a493278c05dc6c1dda69f"}, @@ -6646,6 +6786,130 @@ attrs = ">=22.2.0" rpds-py = ">=0.7.0" typing-extensions = {version = ">=4.4.0", markers = "python_version < \"3.13\""} +[[package]] +name = "regex" +version = "2026.4.4" +description = "Alternative regular expression module, to replace re." +optional = false +python-versions = ">=3.10" +groups = ["dev"] +files = [ + {file = "regex-2026.4.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:74fa82dcc8143386c7c0392e18032009d1db715c25f4ba22d23dc2e04d02a20f"}, + {file = "regex-2026.4.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a85b620a388d6c9caa12189233109e236b3da3deffe4ff11b84ae84e218a274f"}, + {file = "regex-2026.4.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2895506ebe32cc63eeed8f80e6eae453171cfccccab35b70dc3129abec35a5b8"}, + {file = "regex-2026.4.4-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6780f008ee81381c737634e75c24e5a6569cc883c4f8e37a37917ee79efcafd9"}, + {file = "regex-2026.4.4-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:88e9b048345c613f253bea4645b2fe7e579782b82cac99b1daad81e29cc2ed8e"}, + {file = "regex-2026.4.4-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:be061028481186ba62a0f4c5f1cc1e3d5ab8bce70c89236ebe01023883bc903b"}, + {file = "regex-2026.4.4-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d2228c02b368d69b724c36e96d3d1da721561fb9cc7faa373d7bf65e07d75cb5"}, + {file = "regex-2026.4.4-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:0540e5b733618a2f84e9cb3e812c8afa82e151ca8e19cf6c4e95c5a65198236f"}, + {file = "regex-2026.4.4-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:cf9b1b2e692d4877880388934ac746c99552ce6bf40792a767fd42c8c99f136d"}, + {file = "regex-2026.4.4-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:011bb48bffc1b46553ac704c975b3348717f4e4aa7a67522b51906f99da1820c"}, + {file = "regex-2026.4.4-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:8512fcdb43f1bf18582698a478b5ab73f9c1667a5b7548761329ef410cd0a760"}, + {file = "regex-2026.4.4-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:867bddc63109a0276f5a31999e4c8e0eb7bbbad7d6166e28d969a2c1afeb97f9"}, + {file = "regex-2026.4.4-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:1b9a00b83f3a40e09859c78920571dcb83293c8004079653dd22ec14bbfa98c7"}, + {file = "regex-2026.4.4-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:e355be718caf838aa089870259cf1776dc2a4aa980514af9d02c59544d9a8b22"}, + {file = "regex-2026.4.4-cp310-cp310-win32.whl", hash = "sha256:33bfda9684646d323414df7abe5692c61d297dbb0530b28ec66442e768813c59"}, + {file = "regex-2026.4.4-cp310-cp310-win_amd64.whl", hash = "sha256:0709f22a56798457ae317bcce42aacee33c680068a8f14097430d9f9ba364bee"}, + {file = "regex-2026.4.4-cp310-cp310-win_arm64.whl", hash = "sha256:ee9627de8587c1a22201cb16d0296ab92b4df5cdcb5349f4e9744d61db7c7c98"}, + {file = "regex-2026.4.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:b4c36a85b00fadb85db9d9e90144af0a980e1a3d2ef9cd0f8a5bef88054657c6"}, + {file = "regex-2026.4.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:dcb5453ecf9cd58b562967badd1edbf092b0588a3af9e32ee3d05c985077ce87"}, + {file = "regex-2026.4.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:6aa809ed4dc3706cc38594d67e641601bd2f36d5555b2780ff074edfcb136cf8"}, + {file = "regex-2026.4.4-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:33424f5188a7db12958246a54f59a435b6cb62c5cf9c8d71f7cc49475a5fdada"}, + {file = "regex-2026.4.4-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:7d346fccdde28abba117cc9edc696b9518c3307fbfcb689e549d9b5979018c6d"}, + {file = "regex-2026.4.4-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:415a994b536440f5011aa77e50a4274d15da3245e876e5c7f19da349caaedd87"}, + {file = "regex-2026.4.4-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:21e5eb86179b4c67b5759d452ea7c48eb135cd93308e7a260aa489ed2eb423a4"}, + {file = "regex-2026.4.4-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:312ec9dd1ae7d96abd8c5a36a552b2139931914407d26fba723f9e53c8186f86"}, + {file = "regex-2026.4.4-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:a0d2b28aa1354c7cd7f71b7658c4326f7facac106edd7f40eda984424229fd59"}, + {file = "regex-2026.4.4-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:349d7310eddff40429a099c08d995c6d4a4bfaf3ff40bd3b5e5cb5a5a3c7d453"}, + {file = "regex-2026.4.4-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:e7ab63e9fe45a9ec3417509e18116b367e89c9ceb6219222a3396fa30b147f80"}, + {file = "regex-2026.4.4-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:fe896e07a5a2462308297e515c0054e9ec2dd18dfdc9427b19900b37dfe6f40b"}, + {file = "regex-2026.4.4-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:eb59c65069498dbae3c0ef07bbe224e1eaa079825a437fb47a479f0af11f774f"}, + {file = "regex-2026.4.4-cp311-cp311-win32.whl", hash = "sha256:2a5d273181b560ef8397c8825f2b9d57013de744da9e8257b8467e5da8599351"}, + {file = "regex-2026.4.4-cp311-cp311-win_amd64.whl", hash = "sha256:9542ccc1e689e752594309444081582f7be2fdb2df75acafea8a075108566735"}, + {file = "regex-2026.4.4-cp311-cp311-win_arm64.whl", hash = "sha256:b5f9fb784824a042be3455b53d0b112655686fdb7a91f88f095f3fee1e2a2a54"}, + {file = "regex-2026.4.4-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:c07ab8794fa929e58d97a0e1796b8b76f70943fa39df225ac9964615cf1f9d52"}, + {file = "regex-2026.4.4-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:2c785939dc023a1ce4ec09599c032cc9933d258a998d16ca6f2b596c010940eb"}, + {file = "regex-2026.4.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1b1ce5c81c9114f1ce2f9288a51a8fd3aeea33a0cc440c415bf02da323aa0a76"}, + {file = "regex-2026.4.4-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:760ef21c17d8e6a4fe8cf406a97cf2806a4df93416ccc82fc98d25b1c20425be"}, + {file = "regex-2026.4.4-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:7088fcdcb604a4417c208e2169715800d28838fefd7455fbe40416231d1d47c1"}, + {file = "regex-2026.4.4-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:07edca1ba687998968f7db5bc355288d0c6505caa7374f013d27356d93976d13"}, + {file = "regex-2026.4.4-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:993f657a7c1c6ec51b5e0ba97c9817d06b84ea5fa8d82e43b9405de0defdc2b9"}, + {file = "regex-2026.4.4-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:2b69102a743e7569ebee67e634a69c4cb7e59d6fa2e1aa7d3bdbf3f61435f62d"}, + {file = "regex-2026.4.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6dac006c8b6dda72d86ea3d1333d45147de79a3a3f26f10c1cf9287ca4ca0ac3"}, + {file = "regex-2026.4.4-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:50a766ee2010d504554bfb5f578ed2e066898aa26411d57e6296230627cdefa0"}, + {file = "regex-2026.4.4-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:9e2f5217648f68e3028c823df58663587c1507a5ba8419f4fdfc8a461be76043"}, + {file = "regex-2026.4.4-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:39d8de85a08e32632974151ba59c6e9140646dcc36c80423962b1c5c0a92e244"}, + {file = "regex-2026.4.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:55d9304e0e7178dfb1e106c33edf834097ddf4a890e2f676f6c5118f84390f73"}, + {file = "regex-2026.4.4-cp312-cp312-win32.whl", hash = "sha256:04bb679bc0bde8a7bfb71e991493d47314e7b98380b083df2447cda4b6edb60f"}, + {file = "regex-2026.4.4-cp312-cp312-win_amd64.whl", hash = "sha256:db0ac18435a40a2543dbb3d21e161a6c78e33e8159bd2e009343d224bb03bb1b"}, + {file = "regex-2026.4.4-cp312-cp312-win_arm64.whl", hash = "sha256:4ce255cc05c1947a12989c6db801c96461947adb7a59990f1360b5983fab4983"}, + {file = "regex-2026.4.4-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:62f5519042c101762509b1d717b45a69c0139d60414b3c604b81328c01bd1943"}, + {file = "regex-2026.4.4-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:3790ba9fb5dd76715a7afe34dbe603ba03f8820764b1dc929dd08106214ed031"}, + {file = "regex-2026.4.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:8fae3c6e795d7678963f2170152b0d892cf6aee9ee8afc8c45e6be38d5107fe7"}, + {file = "regex-2026.4.4-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:298c3ec2d53225b3bf91142eb9691025bab610e0c0c51592dde149db679b3d17"}, + {file = "regex-2026.4.4-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:e9638791082eaf5b3ac112c587518ee78e083a11c4b28012d8fe2a0f536dfb17"}, + {file = "regex-2026.4.4-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:ae3e764bd4c5ff55035dc82a8d49acceb42a5298edf6eb2fc4d328ee5dd7afae"}, + {file = "regex-2026.4.4-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ffa81f81b80047ba89a3c69ae6a0f78d06f4a42ce5126b0eb2a0a10ad44e0b2e"}, + {file = "regex-2026.4.4-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:f56ebf9d70305307a707911b88469213630aba821e77de7d603f9d2f0730687d"}, + {file = "regex-2026.4.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:773d1dfd652bbffb09336abf890bfd64785c7463716bf766d0eb3bc19c8b7f27"}, + {file = "regex-2026.4.4-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:d51d20befd5275d092cdffba57ded05f3c436317ee56466c8928ac32d960edaf"}, + {file = "regex-2026.4.4-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:0a51cdb3c1e9161154f976cb2bef9894bc063ac82f31b733087ffb8e880137d0"}, + {file = "regex-2026.4.4-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:ae5266a82596114e41fb5302140e9630204c1b5f325c770bec654b95dd54b0aa"}, + {file = "regex-2026.4.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:c882cd92ec68585e9c1cf36c447ec846c0d94edd706fe59e0c198e65822fd23b"}, + {file = "regex-2026.4.4-cp313-cp313-win32.whl", hash = "sha256:05568c4fbf3cb4fa9e28e3af198c40d3237cf6041608a9022285fe567ec3ad62"}, + {file = "regex-2026.4.4-cp313-cp313-win_amd64.whl", hash = "sha256:3384df51ed52db0bea967e21458ab0a414f67cdddfd94401688274e55147bb81"}, + {file = "regex-2026.4.4-cp313-cp313-win_arm64.whl", hash = "sha256:acd38177bd2c8e69a411d6521760806042e244d0ef94e2dd03ecdaa8a3c99427"}, + {file = "regex-2026.4.4-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:f94a11a9d05afcfcfa640e096319720a19cc0c9f7768e1a61fceee6a3afc6c7c"}, + {file = "regex-2026.4.4-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:36bcb9d6d1307ab629edc553775baada2aefa5c50ccc0215fbfd2afcfff43141"}, + {file = "regex-2026.4.4-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:261c015b3e2ed0919157046d768774ecde57f03d8fa4ba78d29793447f70e717"}, + {file = "regex-2026.4.4-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c228cf65b4a54583763645dcd73819b3b381ca8b4bb1b349dee1c135f4112c07"}, + {file = "regex-2026.4.4-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:dd2630faeb6876fb0c287f664d93ddce4d50cd46c6e88e60378c05c9047e08ca"}, + {file = "regex-2026.4.4-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:6a50ab11b7779b849472337191f3a043e27e17f71555f98d0092fa6d73364520"}, + {file = "regex-2026.4.4-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0734f63afe785138549fbe822a8cfeaccd1bae814c5057cc0ed5b9f2de4fc883"}, + {file = "regex-2026.4.4-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:c4ee50606cb1967db7e523224e05f32089101945f859928e65657a2cbb3d278b"}, + {file = "regex-2026.4.4-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:6c1818f37be3ca02dcb76d63f2c7aaba4b0dc171b579796c6fbe00148dfec6b1"}, + {file = "regex-2026.4.4-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:f5bfc2741d150d0be3e4a0401a5c22b06e60acb9aa4daa46d9e79a6dcd0f135b"}, + {file = "regex-2026.4.4-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:504ffa8a03609a087cad81277a629b6ce884b51a24bd388a7980ad61748618ff"}, + {file = "regex-2026.4.4-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:70aadc6ff12e4b444586e57fc30771f86253f9f0045b29016b9605b4be5f7dfb"}, + {file = "regex-2026.4.4-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:f4f83781191007b6ef43b03debc35435f10cad9b96e16d147efe84a1d48bdde4"}, + {file = "regex-2026.4.4-cp313-cp313t-win32.whl", hash = "sha256:e014a797de43d1847df957c0a2a8e861d1c17547ee08467d1db2c370b7568baa"}, + {file = "regex-2026.4.4-cp313-cp313t-win_amd64.whl", hash = "sha256:b15b88b0d52b179712632832c1d6e58e5774f93717849a41096880442da41ab0"}, + {file = "regex-2026.4.4-cp313-cp313t-win_arm64.whl", hash = "sha256:586b89cdadf7d67bf86ae3342a4dcd2b8d70a832d90c18a0ae955105caf34dbe"}, + {file = "regex-2026.4.4-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:2da82d643fa698e5e5210e54af90181603d5853cf469f5eedf9bfc8f59b4b8c7"}, + {file = "regex-2026.4.4-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:54a1189ad9d9357760557c91103d5e421f0a2dabe68a5cdf9103d0dcf4e00752"}, + {file = "regex-2026.4.4-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:76d67d5afb1fe402d10a6403bae668d000441e2ab115191a804287d53b772951"}, + {file = "regex-2026.4.4-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e7cd3e4ee8d80447a83bbc9ab0c8459781fa77087f856c3e740d7763be0df27f"}, + {file = "regex-2026.4.4-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:2e19e18c568d2866d8b6a6dfad823db86193503f90823a8f66689315ba28fbe8"}, + {file = "regex-2026.4.4-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:7698a6f38730fd1385d390d1ed07bb13dce39aa616aca6a6d89bea178464b9a4"}, + {file = "regex-2026.4.4-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:173a66f3651cdb761018078e2d9487f4cf971232c990035ec0eb1cdc6bf929a9"}, + {file = "regex-2026.4.4-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:fa7922bbb2cc84fa062d37723f199d4c0cd200245ce269c05db82d904db66b83"}, + {file = "regex-2026.4.4-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:59f67cd0a0acaf0e564c20bbd7f767286f23e91e2572c5703bf3e56ea7557edb"}, + {file = "regex-2026.4.4-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:475e50f3f73f73614f7cba5524d6de49dee269df00272a1b85e3d19f6d498465"}, + {file = "regex-2026.4.4-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:a1c0c7d67b64d85ac2e1879923bad2f08a08f3004055f2f406ef73c850114bd4"}, + {file = "regex-2026.4.4-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:1371c2ccbb744d66ee63631cc9ca12aa233d5749972626b68fe1a649dd98e566"}, + {file = "regex-2026.4.4-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:59968142787042db793348a3f5b918cf24ced1f23247328530e063f89c128a95"}, + {file = "regex-2026.4.4-cp314-cp314-win32.whl", hash = "sha256:59efe72d37fd5a91e373e5146f187f921f365f4abc1249a5ab446a60f30dd5f8"}, + {file = "regex-2026.4.4-cp314-cp314-win_amd64.whl", hash = "sha256:e0aab3ff447845049d676827d2ff714aab4f73f340e155b7de7458cf53baa5a4"}, + {file = "regex-2026.4.4-cp314-cp314-win_arm64.whl", hash = "sha256:a7a5bb6aa0cf62208bb4fa079b0c756734f8ad0e333b425732e8609bd51ee22f"}, + {file = "regex-2026.4.4-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:97850d0638391bdc7d35dc1c1039974dcb921eaafa8cc935ae4d7f272b1d60b3"}, + {file = "regex-2026.4.4-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:ee7337f88f2a580679f7bbfe69dc86c043954f9f9c541012f49abc554a962f2e"}, + {file = "regex-2026.4.4-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:7429f4e6192c11d659900c0648ba8776243bf396ab95558b8c51a345afeddde6"}, + {file = "regex-2026.4.4-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:dc4f10fbd5dd13dcf4265b4cc07d69ca70280742870c97ae10093e3d66000359"}, + {file = "regex-2026.4.4-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a152560af4f9742b96f3827090f866eeec5becd4765c8e0d3473d9d280e76a5a"}, + {file = "regex-2026.4.4-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:54170b3e95339f415d54651f97df3bff7434a663912f9358237941bbf9143f55"}, + {file = "regex-2026.4.4-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:07f190d65f5a72dcb9cf7106bfc3d21e7a49dd2879eda2207b683f32165e4d99"}, + {file = "regex-2026.4.4-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:9a2741ce5a29d3c84b0b94261ba630ab459a1b847a0d6beca7d62d188175c790"}, + {file = "regex-2026.4.4-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:b26c30df3a28fd9793113dac7385a4deb7294a06c0f760dd2b008bd49a9139bc"}, + {file = "regex-2026.4.4-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:421439d1bee44b19f4583ccf42670ca464ffb90e9fdc38d37f39d1ddd1e44f1f"}, + {file = "regex-2026.4.4-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:b40379b53ecbc747fd9bdf4a0ea14eb8188ca1bd0f54f78893a39024b28f4863"}, + {file = "regex-2026.4.4-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:08c55c13d2eef54f73eeadc33146fb0baaa49e7335eb1aff6ae1324bf0ddbe4a"}, + {file = "regex-2026.4.4-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:9776b85f510062f5a75ef112afe5f494ef1635607bf1cc220c1391e9ac2f5e81"}, + {file = "regex-2026.4.4-cp314-cp314t-win32.whl", hash = "sha256:385edaebde5db5be103577afc8699fea73a0e36a734ba24870be7ffa61119d74"}, + {file = "regex-2026.4.4-cp314-cp314t-win_amd64.whl", hash = "sha256:5d354b18839328927832e2fa5f7c95b7a3ccc39e7a681529e1685898e6436d45"}, + {file = "regex-2026.4.4-cp314-cp314t-win_arm64.whl", hash = "sha256:af0384cb01a33600c49505c27c6c57ab0b27bf84a74e28524c92ca897ebdac9d"}, + {file = "regex-2026.4.4.tar.gz", hash = "sha256:e08270659717f6973523ce3afbafa53515c4dc5dcad637dc215b6fd50f689423"}, +] + [[package]] name = "requests" version = "2.33.1" @@ -6818,7 +7082,7 @@ version = "0.19.1" description = "ruamel.yaml is a YAML parser/emitter that supports roundtrip preservation of comments, seq/map flow style, and map key order" optional = false python-versions = ">=3.9" -groups = ["main"] +groups = ["main", "dev"] files = [ {file = "ruamel_yaml-0.19.1-py3-none-any.whl", hash = "sha256:27592957fedf6e0b62f281e96effd28043345e0e66001f97683aa9a40c667c93"}, {file = "ruamel_yaml-0.19.1.tar.gz", hash = "sha256:53eb66cd27849eff968ebf8f0bf61f46cdac2da1d1f3576dd4ccee9b25c31993"}, @@ -6832,32 +7096,87 @@ oldlibyaml = ["ruamel.yaml.clib ; platform_python_implementation == \"CPython\"" [[package]] name = "ruff" -version = "0.5.7" +version = "0.9.10" description = "An extremely fast Python linter and code formatter, written in Rust." optional = false python-versions = ">=3.7" groups = ["checks"] files = [ - {file = "ruff-0.5.7-py3-none-linux_armv6l.whl", hash = "sha256:548992d342fc404ee2e15a242cdbea4f8e39a52f2e7752d0e4cbe88d2d2f416a"}, - {file = "ruff-0.5.7-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:00cc8872331055ee017c4f1071a8a31ca0809ccc0657da1d154a1d2abac5c0be"}, - {file = "ruff-0.5.7-py3-none-macosx_11_0_arm64.whl", hash = "sha256:eaf3d86a1fdac1aec8a3417a63587d93f906c678bb9ed0b796da7b59c1114a1e"}, - {file = "ruff-0.5.7-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a01c34400097b06cf8a6e61b35d6d456d5bd1ae6961542de18ec81eaf33b4cb8"}, - {file = "ruff-0.5.7-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fcc8054f1a717e2213500edaddcf1dbb0abad40d98e1bd9d0ad364f75c763eea"}, - {file = "ruff-0.5.7-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7f70284e73f36558ef51602254451e50dd6cc479f8b6f8413a95fcb5db4a55fc"}, - {file = "ruff-0.5.7-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:a78ad870ae3c460394fc95437d43deb5c04b5c29297815a2a1de028903f19692"}, - {file = "ruff-0.5.7-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9ccd078c66a8e419475174bfe60a69adb36ce04f8d4e91b006f1329d5cd44bcf"}, - {file = "ruff-0.5.7-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7e31c9bad4ebf8fdb77b59cae75814440731060a09a0e0077d559a556453acbb"}, - {file = "ruff-0.5.7-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8d796327eed8e168164346b769dd9a27a70e0298d667b4ecee6877ce8095ec8e"}, - {file = "ruff-0.5.7-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:4a09ea2c3f7778cc635e7f6edf57d566a8ee8f485f3c4454db7771efb692c499"}, - {file = "ruff-0.5.7-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:a36d8dcf55b3a3bc353270d544fb170d75d2dff41eba5df57b4e0b67a95bb64e"}, - {file = "ruff-0.5.7-py3-none-musllinux_1_2_i686.whl", hash = "sha256:9369c218f789eefbd1b8d82a8cf25017b523ac47d96b2f531eba73770971c9e5"}, - {file = "ruff-0.5.7-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:b88ca3db7eb377eb24fb7c82840546fb7acef75af4a74bd36e9ceb37a890257e"}, - {file = "ruff-0.5.7-py3-none-win32.whl", hash = "sha256:33d61fc0e902198a3e55719f4be6b375b28f860b09c281e4bdbf783c0566576a"}, - {file = "ruff-0.5.7-py3-none-win_amd64.whl", hash = "sha256:083bbcbe6fadb93cd86709037acc510f86eed5a314203079df174c40bbbca6b3"}, - {file = "ruff-0.5.7-py3-none-win_arm64.whl", hash = "sha256:2dca26154ff9571995107221d0aeaad0e75a77b5a682d6236cf89a58c70b76f4"}, - {file = "ruff-0.5.7.tar.gz", hash = "sha256:8dfc0a458797f5d9fb622dd0efc52d796f23f0a1493a9527f4e49a550ae9a7e5"}, + {file = "ruff-0.9.10-py3-none-linux_armv6l.whl", hash = "sha256:eb4d25532cfd9fe461acc83498361ec2e2252795b4f40b17e80692814329e42d"}, + {file = "ruff-0.9.10-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:188a6638dab1aa9bb6228a7302387b2c9954e455fb25d6b4470cb0641d16759d"}, + {file = "ruff-0.9.10-py3-none-macosx_11_0_arm64.whl", hash = "sha256:5284dcac6b9dbc2fcb71fdfc26a217b2ca4ede6ccd57476f52a587451ebe450d"}, + {file = "ruff-0.9.10-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:47678f39fa2a3da62724851107f438c8229a3470f533894b5568a39b40029c0c"}, + {file = "ruff-0.9.10-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:99713a6e2766b7a17147b309e8c915b32b07a25c9efd12ada79f217c9c778b3e"}, + {file = "ruff-0.9.10-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:524ee184d92f7c7304aa568e2db20f50c32d1d0caa235d8ddf10497566ea1a12"}, + {file = "ruff-0.9.10-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:df92aeac30af821f9acf819fc01b4afc3dfb829d2782884f8739fb52a8119a16"}, + {file = "ruff-0.9.10-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:de42e4edc296f520bb84954eb992a07a0ec5a02fecb834498415908469854a52"}, + {file = "ruff-0.9.10-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d257f95b65806104b6b1ffca0ea53f4ef98454036df65b1eda3693534813ecd1"}, + {file = "ruff-0.9.10-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b60dec7201c0b10d6d11be00e8f2dbb6f40ef1828ee75ed739923799513db24c"}, + {file = "ruff-0.9.10-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:d838b60007da7a39c046fcdd317293d10b845001f38bcb55ba766c3875b01e43"}, + {file = "ruff-0.9.10-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:ccaf903108b899beb8e09a63ffae5869057ab649c1e9231c05ae354ebc62066c"}, + {file = "ruff-0.9.10-py3-none-musllinux_1_2_i686.whl", hash = "sha256:f9567d135265d46e59d62dc60c0bfad10e9a6822e231f5b24032dba5a55be6b5"}, + {file = "ruff-0.9.10-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:5f202f0d93738c28a89f8ed9eaba01b7be339e5d8d642c994347eaa81c6d75b8"}, + {file = "ruff-0.9.10-py3-none-win32.whl", hash = "sha256:bfb834e87c916521ce46b1788fbb8484966e5113c02df216680102e9eb960029"}, + {file = "ruff-0.9.10-py3-none-win_amd64.whl", hash = "sha256:f2160eeef3031bf4b17df74e307d4c5fb689a6f3a26a2de3f7ef4044e3c484f1"}, + {file = "ruff-0.9.10-py3-none-win_arm64.whl", hash = "sha256:5fd804c0327a5e5ea26615550e706942f348b197d5475ff34c19733aee4b2e69"}, + {file = "ruff-0.9.10.tar.gz", hash = "sha256:9bacb735d7bada9cfb0f2c227d3658fc443d90a727b47f206fb33f52f3c0eac7"}, +] + +[[package]] +name = "safety" +version = "3.7.0" +description = "Scan dependencies for known vulnerabilities and licenses." +optional = false +python-versions = ">=3.9" +groups = ["dev"] +files = [ + {file = "safety-3.7.0-py3-none-any.whl", hash = "sha256:65e71db45eb832e8840e3456333d44c23927423753d5610596a09e909a66d2bf"}, + {file = "safety-3.7.0.tar.gz", hash = "sha256:daec15a393cafc32b846b7ef93f9c952a1708863e242341ab5bde2e4beabb54e"}, +] + +[package.dependencies] +authlib = ">=1.2.0" +click = ">=8.0.2" +dparse = ">=0.6.4" +filelock = ">=3.16.1,<4.0" +httpx = "*" +jinja2 = ">=3.1.0" +marshmallow = ">=3.15.0" +nltk = ">=3.9" +packaging = ">=21.0" +pydantic = ">=2.6.0" +requests = "*" +ruamel-yaml = ">=0.17.21" +safety-schemas = "0.0.16" +tenacity = ">=8.1.0" +tomlkit = "*" +typer = ">=0.16.0" +typing-extensions = ">=4.7.1" + +[package.extras] +github = ["pygithub (>=1.43.3)"] +gitlab = ["python-gitlab (>=1.3.0)"] +spdx = ["spdx-tools (>=0.8.2)"] + +[[package]] +name = "safety-schemas" +version = "0.0.16" +description = "Schemas for Safety tools" +optional = false +python-versions = ">=3.8" +groups = ["dev"] +files = [ + {file = "safety_schemas-0.0.16-py3-none-any.whl", hash = "sha256:6760515d3fd1e6535b251cd73014bd431d12fe0bfb8b6e8880a9379b5ab7aa44"}, + {file = "safety_schemas-0.0.16.tar.gz", hash = "sha256:3bb04d11bd4b5cc79f9fa183c658a6a8cf827a9ceec443a5ffa6eed38a50a24e"}, ] +[package.dependencies] +dparse = ">=0.6.4" +packaging = ">=21.0" +pydantic = ">=2.6.0" +ruamel-yaml = ">=0.17.21" +typing-extensions = ">=4.7.1" + [[package]] name = "scikit-learn" version = "1.8.0" @@ -7119,7 +7438,7 @@ version = "1.5.4" description = "Tool to Detect Surrounding Shell" optional = false python-versions = ">=3.7" -groups = ["main"] +groups = ["main", "dev"] files = [ {file = "shellingham-1.5.4-py2.py3-none-any.whl", hash = "sha256:7ecfff8f2fd72616f7481040475a65b2bf8af90a56c89140852d1120324e8686"}, {file = "shellingham-1.5.4.tar.gz", hash = "sha256:8dbca0739d487e5bd35ab3ca4b36e11c4078f3a234bfce294b0a0291363404de"}, @@ -7449,7 +7768,7 @@ version = "9.1.4" description = "Retry code until it succeeds" optional = false python-versions = ">=3.10" -groups = ["main"] +groups = ["main", "dev"] files = [ {file = "tenacity-9.1.4-py3-none-any.whl", hash = "sha256:6095a360c919085f28c6527de529e76a06ad89b23659fa881ae0649b867a9d55"}, {file = "tenacity-9.1.4.tar.gz", hash = "sha256:adb31d4c263f2bd041081ab33b498309a57c77f9acf2db65aadf0898179cf93a"}, @@ -7561,7 +7880,7 @@ version = "0.14.0" description = "Style preserving TOML library" optional = false python-versions = ">=3.9" -groups = ["main", "commits"] +groups = ["main", "commits", "dev"] files = [ {file = "tomlkit-0.14.0-py3-none-any.whl", hash = "sha256:592064ed85b40fa213469f81ac584f67a4f2992509a7c3ea2d632208623a3680"}, {file = "tomlkit-0.14.0.tar.gz", hash = "sha256:cf00efca415dbd57575befb1f6634c4f42d2d87dbba376128adb42c121b87064"}, @@ -7593,7 +7912,7 @@ version = "4.67.3" description = "Fast, Extensible Progress Meter" optional = false python-versions = ">=3.7" -groups = ["main"] +groups = ["main", "dev"] files = [ {file = "tqdm-4.67.3-py3-none-any.whl", hash = "sha256:ee1e4c0e59148062281c49d80b25b67771a127c85fc9676d3be5f243206826bf"}, {file = "tqdm-4.67.3.tar.gz", hash = "sha256:7d825f03f89244ef73f1d4ce193cb1774a8179fd96f31d7e1dcde62092b960bb"}, @@ -7674,7 +7993,7 @@ version = "0.25.0" description = "Typer, build great CLIs. Easy to code. Based on Python type hints." optional = false python-versions = ">=3.10" -groups = ["main"] +groups = ["main", "dev"] files = [ {file = "typer-0.25.0-py3-none-any.whl", hash = "sha256:ac01b48823d3db9a83c9e164338057eadbb1c9957a2a6b4eeb486669c560b5dc"}, {file = "typer-0.25.0.tar.gz", hash = "sha256:123eaf9f19bb40fd268310e12a542c0c6b4fab9c98d9d23342a01ff95e3ce930"}, @@ -7720,7 +8039,7 @@ version = "0.4.2" description = "Runtime typing introspection tools" optional = false python-versions = ">=3.9" -groups = ["main", "checks"] +groups = ["main", "checks", "dev"] files = [ {file = "typing_inspection-0.4.2-py3-none-any.whl", hash = "sha256:4ed1cacbdc298c220f1bd249ed5287caa16f34d44ef4e9c3d0cbad5b521545e7"}, {file = "typing_inspection-0.4.2.tar.gz", hash = "sha256:ba561c48a67c5958007083d386c3295464928b01faa735ab8547c5692e87f464"}, @@ -8307,4 +8626,4 @@ testing = ["coverage[toml]", "zope.event", "zope.testing"] [metadata] lock-version = "2.1" python-versions = ">=3.12,<3.13" -content-hash = "acb70ab3a832cd472822af7fa11c189c58652c1658a21f600adb234b0afa2867" +content-hash = "c4a0e673ee0f1b757ab3f35c80a6f561c01a6ab6f3d08e55230db658c9b19f2d" diff --git a/pyproject.toml b/pyproject.toml index 6e942fd..9c62147 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -21,7 +21,7 @@ regression_model_template = "regression_model_template.scripts:main" python = ">=3.12,<3.13" loguru = "^0.7.2" matplotlib = "^3.9.0" -mlflow = "^3.10.1" +mlflow = "^3.11.1" numpy = "^1.26.4" omegaconf = "^2.3.0" pandas = "^2.2.2" @@ -46,7 +46,7 @@ confluent-kafka = "^2.8.2" fastapi = "0.124.0" pyopenssl = "^26.0.0" diskcache = "^5.6.3" -starlette = "^0.49.1" +starlette = "^0.49.3" [tool.poetry.group.checks.dependencies] bandit = "^1.7.9" @@ -56,7 +56,7 @@ pytest = "^9.0.3" pytest-cov = "^5.0.0" pytest-xdist = "^3.6.1" pandera = { extras = ["mypy"], version = "^0.20.1" } -ruff = "^0.5.0" +ruff = "^0.9.0" pytest-mock = "^3.14.0" pytest-asyncio = "^1.3.0" @@ -67,6 +67,7 @@ pre-commit = "^3.7.1" [tool.poetry.group.dev.dependencies] invoke = "^2.2.0" pip-audit = "^2.10.0" +safety = "^3.7.0" [tool.poetry.group.docs.dependencies] pdoc = "^14.5.1" diff --git a/requirements.txt b/requirements.txt index a33b656..a3a9f34 100644 --- a/requirements.txt +++ b/requirements.txt @@ -16,12 +16,9 @@ async-timeout==5.0.1 ; python_version == "3.12" asyncssh==2.22.0 ; python_version == "3.12" atpublic==7.0.0 ; python_version == "3.12" attrs==26.1.0 ; python_version == "3.12" -bandit==1.9.4 ; python_version == "3.12" billiard==4.2.4 ; python_version == "3.12" blinker==1.9.0 ; python_version == "3.12" -boolean-py==5.0 ; python_version == "3.12" brotli==1.2.0 ; python_version == "3.12" -cachecontrol[filecache]==0.14.4 ; python_version == "3.12" cachetools==7.0.6 ; python_version == "3.12" celery==5.6.3 ; python_version == "3.12" certifi==2026.4.22 ; python_version == "3.12" @@ -36,13 +33,9 @@ colorama==0.4.6 ; python_version == "3.12" configobj==5.0.9 ; python_version == "3.12" confluent-kafka==2.14.0 ; python_version == "3.12" contourpy==1.3.3 ; python_version == "3.12" -coverage==7.13.5 ; python_version == "3.12" -coverage[toml]==7.13.5 ; python_version == "3.12" cryptography==46.0.7 ; python_version == "3.12" cycler==0.12.1 ; python_version == "3.12" -cyclonedx-python-lib==11.7.0 ; python_version == "3.12" databricks-sdk==0.105.0 ; python_version == "3.12" -defusedxml==0.7.1 ; python_version == "3.12" deprecated==1.3.1 ; python_version == "3.12" dictdiffer==0.9.0 ; python_version == "3.12" diskcache==5.6.3 ; python_version == "3.12" @@ -58,7 +51,6 @@ dvc-studio-client==0.22.0 ; python_version == "3.12" dvc-task==0.40.2 ; python_version == "3.12" dvc==3.67.1 ; python_version == "3.12" entrypoints==0.4 ; python_version == "3.12" -execnet==2.1.2 ; python_version == "3.12" fastapi==0.124.0 ; python_version == "3.12" filelock==3.29.0 ; python_version == "3.12" flask-cors==6.0.2 ; python_version == "3.12" @@ -91,16 +83,12 @@ hydra-core==1.3.2 ; python_version == "3.12" idna==3.13 ; python_version == "3.12" importlib-metadata==8.5.0 ; python_version == "3.12" importlib-resources==6.5.2 ; python_version == "3.12" -iniconfig==2.3.0 ; python_version == "3.12" -invoke==2.2.1 ; python_version == "3.12" iterative-telemetry==0.0.10 ; python_version == "3.12" itsdangerous==2.2.0 ; python_version == "3.12" jinja2==3.1.6 ; python_version == "3.12" joblib==1.5.3 ; python_version == "3.12" kiwisolver==1.5.0 ; python_version == "3.12" kombu==5.6.2 ; python_version == "3.12" -librt==0.9.0 ; platform_python_implementation != "PyPy" and python_version == "3.12" -license-expression==30.4.4 ; python_version == "3.12" llvmlite==0.47.0 ; python_version == "3.12" loguru==0.7.3 ; python_version == "3.12" mako==1.3.11 ; python_version == "3.12" @@ -113,11 +101,9 @@ mlflow-tracing==3.11.1 ; python_version == "3.12" mlflow==3.11.1 ; python_version == "3.12" mlserver-mlflow==1.7.1 ; python_version == "3.12" mlserver==1.7.2rc1 ; python_version == "3.12" -msgpack==1.1.2 ; python_version == "3.12" multidict==6.7.1 ; python_version == "3.12" multimethod==1.10 ; python_version == "3.12" mypy-extensions==1.1.0 ; python_version == "3.12" -mypy==1.20.2 ; python_version == "3.12" networkx==3.6.1 ; python_version == "3.12" numba==0.65.1 ; python_version == "3.12" numpy==1.26.4 ; python_version == "3.12" @@ -136,21 +122,13 @@ opentelemetry-sdk==1.30.0 ; python_version == "3.12" opentelemetry-semantic-conventions==0.51b0 ; python_version == "3.12" opentelemetry-util-http==0.51b0 ; python_version == "3.12" orjson==3.11.8 ; python_version == "3.12" -packageurl-python==0.17.6 ; python_version == "3.12" packaging==26.2 ; python_version == "3.12" -pandas-stubs==3.0.0.260204 ; python_version == "3.12" pandas==2.3.3 ; python_version == "3.12" pandera==0.20.4 ; python_version == "3.12" -pandera[mypy]==0.20.4 ; python_version == "3.12" pathspec==1.1.1 ; python_version == "3.12" pillow==12.2.0 ; python_version == "3.12" -pip-api==0.0.34 ; python_version == "3.12" -pip-audit==2.10.0 ; python_version == "3.12" -pip-requirements-parser==32.0.1 ; python_version == "3.12" -pip==26.1 ; python_version == "3.12" platformdirs==4.9.6 ; python_version == "3.12" plotly==5.24.1 ; python_version == "3.12" -pluggy==1.6.0 ; python_version == "3.12" plyer==2.1.0 ; python_version == "3.12" prettytable==3.17.0 ; python_version == "3.12" prometheus-client==0.25.0 ; python_version == "3.12" @@ -159,7 +137,6 @@ propcache==0.4.1 ; python_version == "3.12" protobuf==5.29.6 ; python_version == "3.12" psutil==6.1.1 ; python_version == "3.12" py-grpc-prometheus==0.8.0 ; python_version == "3.12" -py-serializable==2.1.0 ; python_version == "3.12" pyarrow==17.0.0 ; python_version == "3.12" pyasn1-modules==0.4.2 ; python_version == "3.12" pyasn1==0.6.3 ; python_version == "3.12" @@ -174,11 +151,6 @@ pygtrie==2.5.0 ; python_version == "3.12" pynvml==11.5.3 ; python_version == "3.12" pyopenssl==26.1.0 ; python_version == "3.12" pyparsing==3.3.2 ; python_version == "3.12" -pytest-asyncio==1.3.0 ; python_version == "3.12" -pytest-cov==5.0.0 ; python_version == "3.12" -pytest-mock==3.15.1 ; python_version == "3.12" -pytest-xdist==3.8.0 ; python_version == "3.12" -pytest==9.0.3 ; python_version == "3.12" python-dateutil==2.9.0.post0 ; python_version == "3.12" python-dotenv==1.2.2 ; python_version == "3.12" python-multipart==0.0.27 ; python_version == "3.12" @@ -189,7 +161,6 @@ pyyaml==6.0.3 ; python_version == "3.12" requests==2.33.1 ; python_version == "3.12" rich==15.0.0 ; python_version == "3.12" ruamel-yaml==0.19.1 ; python_version == "3.12" -ruff==0.5.7 ; python_version == "3.12" scikit-learn==1.8.0 ; python_version == "3.12" scipy==1.17.1 ; python_version == "3.12" scmrepo==3.6.2 ; python_version == "3.12" @@ -203,18 +174,14 @@ six==1.17.0 ; python_version == "3.12" skops==0.14.0 ; python_version == "3.12" slicer==0.0.8 ; python_version == "3.12" smmap==5.0.3 ; python_version == "3.12" -sortedcontainers==2.4.0 ; python_version == "3.12" sqlalchemy==2.0.49 ; python_version == "3.12" sqlparse==0.5.5 ; python_version == "3.12" sqltrie==0.11.2 ; python_version == "3.12" starlette-exporter==0.23.0 ; python_version == "3.12" starlette==0.49.3 ; python_version == "3.12" -stevedore==5.7.0 ; python_version == "3.12" tabulate==0.10.0 ; python_version == "3.12" tenacity==9.1.4 ; python_version == "3.12" threadpoolctl==3.6.0 ; python_version == "3.12" -tomli-w==1.2.0 ; python_version == "3.12" -tomli==2.4.1 ; python_version == "3.12" tomlkit==0.14.0 ; python_version == "3.12" tqdm==4.67.3 ; python_version == "3.12" tritonclient[http]==2.68.0 ; python_version == "3.12" From 1b584d06d7d3c243d729ddf661ec19fc197848e7 Mon Sep 17 00:00:00 2001 From: lgcorzo Date: Tue, 28 Apr 2026 21:24:04 +0200 Subject: [PATCH 2/3] Security remediation and Poetry 2.0 migration - Migrated pyproject.toml to PEP 621 standard - Updated dependencies (mlflow, ruff, fastapi) - Fixed code formatting with ruff format - Resolved mypy unused-ignore error in kafka_app.py - Updated poetry.lock for Poetry 2.0 --- poetry.lock | 2 +- pyproject.toml | 70 ++++++++++--------- .../controller/kafka_app.py | 2 +- tests/core/test_metrics.py | 12 ++-- tests/core/test_models.py | 24 +++---- tests/io/test_registries.py | 18 ++--- tests/io/test_services.py | 6 +- tests/jobs/test_evaluations.py | 30 ++++---- tests/jobs/test_explanations.py | 18 ++--- tests/jobs/test_training.py | 42 +++++------ tests/jobs/test_tuning.py | 12 ++-- tests/utils/test_signers.py | 12 ++-- tests/utils/test_splitters.py | 6 +- 13 files changed, 128 insertions(+), 126 deletions(-) diff --git a/poetry.lock b/poetry.lock index ecf3568..aea06e0 100644 --- a/poetry.lock +++ b/poetry.lock @@ -8626,4 +8626,4 @@ testing = ["coverage[toml]", "zope.event", "zope.testing"] [metadata] lock-version = "2.1" python-versions = ">=3.12,<3.13" -content-hash = "c4a0e673ee0f1b757ab3f35c80a6f561c01a6ab6f3d08e55230db658c9b19f2d" +content-hash = "84a776711b145c7506fcbe18eb3997e978dd8e698ec06919efca101f1bed4b66" diff --git a/pyproject.toml b/pyproject.toml index 9c62147..3e0780b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,10 +1,10 @@ # https://python-poetry.org/docs/pyproject/ -[tool.poetry] +[project] name = "regression_model_template" version = "2.0.0" description = "Predict the number of regression_model_template available." -authors = ["lgcorzo"] +authors = [{ name = "lgcorzo" }] readme = "README.md" license = "MIT" keywords = ["mlops", "python", "package"] @@ -12,41 +12,43 @@ classifiers = [ "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.12", ] -packages = [{ include = "regression_model_template", from = "src" }] +requires-python = ">=3.12,<3.13" +dependencies = [ + "loguru (>=0.7.2,<0.8.0)", + "matplotlib (>=3.9.0,<4.0.0)", + "mlflow (>=3.11.1,<4.0.0)", + "numpy (>=1.26.4,<2.0.0)", + "omegaconf (>=2.3.0,<3.0.0)", + "pandas (>=2.2.2,<3.0.0)", + "pandera (>=0.20.1,<0.21.0)", + "plotly (>=5.22.0,<6.0.0)", + "plyer (>=2.1.0,<3.0.0)", + "psutil (>=6.0.0,<7.0.0)", + "pyarrow (>=17.0.0,<18.0.0)", + "pydantic (>=2.7.4,<3.0.0)", + "pydantic-settings (>=2.3.4,<3.0.0)", + "pynvml (>=11.5.0,<12.0.0)", + "setuptools (>=78.1.1,<79.0.0)", + "scikit-learn (>=1.5.0,<2.0.0)", + "shap (>=0.46.0,<0.47.0)", + "dvc (>=3.67.1,<4.0.0)", + "mlserver (>=1.7.1,<2.0.0)", + "mlserver-mlflow (>=1.7.1,<2.0.0)", + "opentelemetry-instrumentation (>=0.51b0,<0.52)", + "opentelemetry-exporter-otlp-proto-http (>=1.30.0,<2.0.0)", + "opentelemetry-exporter-otlp (>=1.30.0,<2.0.0)", + "confluent-kafka (>=2.8.2,<3.0.0)", + "fastapi (==0.124.0)", + "pyopenssl (>=26.0.0,<27.0.0)", + "diskcache (>=5.6.3,<6.0.0)", + "starlette (>=0.49.3,<0.50.0)", +] -[tool.poetry.scripts] +[project.scripts] regression_model_template = "regression_model_template.scripts:main" -[tool.poetry.dependencies] -python = ">=3.12,<3.13" -loguru = "^0.7.2" -matplotlib = "^3.9.0" -mlflow = "^3.11.1" -numpy = "^1.26.4" -omegaconf = "^2.3.0" -pandas = "^2.2.2" -pandera = "^0.20.1" -plotly = "^5.22.0" -plyer = "^2.1.0" -psutil = "^6.0.0" -pyarrow = "^17.0.0" -pydantic = "^2.7.4" -pydantic-settings = "^2.3.4" -pynvml = "^11.5.0" -setuptools = "^78.1.1" -scikit-learn = "^1.5.0" -shap = "^0.46.0" -dvc = "^3.67.1" -mlserver = "^1.7.1" -mlserver-mlflow = "^1.7.1" -opentelemetry-instrumentation = "^0.51b0" -opentelemetry-exporter-otlp-proto-http = "^1.30.0" -opentelemetry-exporter-otlp = "^1.30.0" -confluent-kafka = "^2.8.2" -fastapi = "0.124.0" -pyopenssl = "^26.0.0" -diskcache = "^5.6.3" -starlette = "^0.49.3" +[tool.poetry] +packages = [{ include = "regression_model_template", from = "src" }] [tool.poetry.group.checks.dependencies] bandit = "^1.7.9" diff --git a/src/regression_model_template/controller/kafka_app.py b/src/regression_model_template/controller/kafka_app.py index 8d1a826..7b69d15 100644 --- a/src/regression_model_template/controller/kafka_app.py +++ b/src/regression_model_template/controller/kafka_app.py @@ -55,7 +55,7 @@ ) # Security Middlewares -app.add_middleware(ProxyHeadersMiddleware, trusted_hosts=TRUSTED_PROXIES) # type: ignore[arg-type] +app.add_middleware(ProxyHeadersMiddleware, trusted_hosts=TRUSTED_PROXIES) app.add_middleware(TrustedHostMiddleware, allowed_hosts=ALLOWED_HOSTS) diff --git a/tests/core/test_metrics.py b/tests/core/test_metrics.py index 30c3912..75649ef 100644 --- a/tests/core/test_metrics.py +++ b/tests/core/test_metrics.py @@ -45,13 +45,13 @@ def test_sklearn_metric( assert low <= scorer <= high, "Scorer should be in the expected interval!" # - mlflow metric assert mlflow_metric.name == metric.name, "Mlflow metric name should be the same!" - assert ( - mlflow_metric.greater_is_better == metric.greater_is_better - ), "Mlflow metric greater is better should be the same!" + assert mlflow_metric.greater_is_better == metric.greater_is_better, ( + "Mlflow metric greater is better should be the same!" + ) # - mlflow results - assert mlflow_results.metrics == { - metric.name: score * (1 if greater_is_better else -1) - }, "Mlflow results metrics should have the same name and score!" + assert mlflow_results.metrics == {metric.name: score * (1 if greater_is_better else -1)}, ( + "Mlflow results metrics should have the same name and score!" + ) # %% THRESHOLDS diff --git a/tests/core/test_models.py b/tests/core/test_models.py index a12d32f..5a29022 100644 --- a/tests/core/test_models.py +++ b/tests/core/test_models.py @@ -41,15 +41,15 @@ def predict(self, inputs: schemas.Inputs) -> schemas.Outputs: "a": 10, "b": 20, }, "Model should have the given params after set_params!" - assert isinstance( - explain_model_error.value, NotImplementedError - ), "Model should raise NotImplementedError for explain_model_error()!" - assert isinstance( - explain_samples_error.value, NotImplementedError - ), "Model should raise NotImplementedError for explain_samples_error()!" - assert isinstance( - get_internal_model_error.value, NotImplementedError - ), "Model should raise NotImplementedError for get_internal_model_error()!" + assert isinstance(explain_model_error.value, NotImplementedError), ( + "Model should raise NotImplementedError for explain_model_error()!" + ) + assert isinstance(explain_samples_error.value, NotImplementedError), ( + "Model should raise NotImplementedError for explain_samples_error()!" + ) + assert isinstance(get_internal_model_error.value, NotImplementedError), ( + "Model should raise NotImplementedError for get_internal_model_error()!" + ) def test_baseline_sklearn_model( @@ -78,6 +78,6 @@ def test_baseline_sklearn_model( assert len(shap_values.columns) >= len(inputs_test.columns), "SHAP values should have more features than inputs!" # - feature importances assert feature_importances["importance"].sum() == 1.0, "Feature importances should add up to 1.0!" - assert len(feature_importances["feature"]) >= len( - inputs_train.columns - ), "Feature importances should have more features than inputs!" + assert len(feature_importances["feature"]) >= len(inputs_train.columns), ( + "Feature importances should have more features than inputs!" + ) diff --git a/tests/io/test_registries.py b/tests/io/test_registries.py index 785dc2a..ad413bc 100644 --- a/tests/io/test_registries.py +++ b/tests/io/test_registries.py @@ -37,9 +37,9 @@ def test_uri_for_model_alias_or_version() -> None: version_uri = registries.uri_for_model_alias_or_version(name=name, alias_or_version=version) # then assert alias_uri == registries.uri_for_model_alias(name=name, alias=alias), "The alias URI should be valid!" - assert version_uri == registries.uri_for_model_version( - name=name, version=version - ), "The version URI should be valid!" + assert version_uri == registries.uri_for_model_version(name=name, version=version), ( + "The version URI should be valid!" + ) # %% SAVERS/LOADERS/REGISTERS @@ -82,9 +82,9 @@ def test_custom_pipeline( # - adapter assert adapter.model.metadata.run_id == version.run_id, "The adapter model run id should be the same!" assert adapter.model.metadata.signature == signature, "The adapter model signature should be the same!" - assert ( - adapter.model.metadata.flavors.get("python_function") is not None - ), "The adapter model should have a python_function flavor!" + assert adapter.model.metadata.flavors.get("python_function") is not None, ( + "The adapter model should have a python_function flavor!" + ) # - output # assert schemas.OutputsSchema.check(outputs) is not None, "Outputs should be valid!" @@ -128,9 +128,9 @@ def test_builtin_pipeline( # - adapter assert adapter.model.metadata.run_id == version.run_id, "The adapter model run id should be the same!" assert adapter.model.metadata.signature == signature, "The adapter model signature should be the same!" - assert ( - adapter.model.metadata.flavors.get("python_function") is not None - ), "The adapter model should have a python_function flavor!" + assert adapter.model.metadata.flavors.get("python_function") is not None, ( + "The adapter model should have a python_function flavor!" + ) assert adapter.model.metadata.flavors.get(flavor), f"The model should have a built-in model flavor: {flavor}!" # - output assert schemas.OutputsSchema.check(outputs) is not None, "Outputs should be valid!" diff --git a/tests/io/test_services.py b/tests/io/test_services.py index 8755fb3..645f82c 100644 --- a/tests/io/test_services.py +++ b/tests/io/test_services.py @@ -39,9 +39,9 @@ def test_alerts_service(enable: bool, mocker: pm.MockerFixture, capsys: pc.Captu plyer.notification.notify.assert_not_called(), "Notification method should not be called!", ) - assert ( - capsys.readouterr().out == "[regression_model_template] test: hello\n" - ), "Notification should be printed to stdout!" + assert capsys.readouterr().out == "[regression_model_template] test: hello\n", ( + "Notification should be printed to stdout!" + ) def test_mlflow_service(mlflow_service: services.MlflowService) -> None: diff --git a/tests/jobs/test_evaluations.py b/tests/jobs/test_evaluations.py index 10ba9d0..bad2868 100644 --- a/tests/jobs/test_evaluations.py +++ b/tests/jobs/test_evaluations.py @@ -93,13 +93,13 @@ def test_evaluations_job( assert out["targets"].ndim == out["targets_"].ndim == 2, "Targets should be a dataframe!" # - lineage assert out["inputs_lineage"].name == "inputs", "Inputs lineage name should be inputs!" - assert ( - out["inputs_lineage"].source.uri == inputs_reader.path - ), "Inputs lineage source should be the inputs reader path!" + assert out["inputs_lineage"].source.uri == inputs_reader.path, ( + "Inputs lineage source should be the inputs reader path!" + ) assert out["targets_lineage"].name == "targets", "Targets lineage name should be targets!" - assert ( - out["targets_lineage"].source.uri == targets_reader.path - ), "Targets lineage source should be the targets reader path!" + assert out["targets_lineage"].source.uri == targets_reader.path, ( + "Targets lineage source should be the targets reader path!" + ) assert out["targets_lineage"].targets == schemas.TargetsSchema.cnt, "Targets lineage target should be cnt!" # - dataset assert out["dataset"].name == "evaluation", "Dataset name should be evaluation!" @@ -113,17 +113,17 @@ def test_evaluations_job( # - extra metrics assert len(out["extra_metrics"]) == len(job.metrics), "Extra metrics should have the same length as metrics!" assert out["extra_metrics"][0].name == job.metrics[0].name, "Extra metrics name should be the same!" - assert ( - out["extra_metrics"][0].greater_is_better == job.metrics[0].greater_is_better - ), "Extra metrics greatter is better should be the same!" + assert out["extra_metrics"][0].greater_is_better == job.metrics[0].greater_is_better, ( + "Extra metrics greatter is better should be the same!" + ) # - validation thresholds - assert ( - out["validation_thresholds"].keys() == thresholds.keys() - ), "Validation thresholds should have the same keys as thresholds!" + assert out["validation_thresholds"].keys() == thresholds.keys(), ( + "Validation thresholds should have the same keys as thresholds!" + ) # - evaluations - assert ( - out["evaluations"].metrics["example_count"] == inputs_reader.limit - ), "Evaluations should have the same number of examples as the inputs!" + assert out["evaluations"].metrics["example_count"] == inputs_reader.limit, ( + "Evaluations should have the same number of examples as the inputs!" + ) assert job.metrics[0].name in out["evaluations"].metrics, "Metric should be logged in Mlflow!" # - mlflow tracking experiment = mlflow_service.client().get_experiment_by_name(name=mlflow_service.experiment_name) diff --git a/tests/jobs/test_explanations.py b/tests/jobs/test_explanations.py index b3fda81..f49c168 100644 --- a/tests/jobs/test_explanations.py +++ b/tests/jobs/test_explanations.py @@ -59,15 +59,15 @@ def test_explanations_job( # - model assert isinstance(out["model"], models.Model), "Model should be an instance of a project Model!" # - model explanations - assert len(out["models_explanations"].index) >= len( - out["inputs_samples"].columns - ), "Model explanations should have at least as many columns as inputs samples!" + assert len(out["models_explanations"].index) >= len(out["inputs_samples"].columns), ( + "Model explanations should have at least as many columns as inputs samples!" + ) # - samples explanations - assert len(out["samples_explanations"].index) == len( - out["inputs_samples"].index - ), "Samples explanations should have the same number of rows as inputs samples!" - assert len(out["samples_explanations"].columns) >= len( - out["inputs_samples"].columns - ), "Samples explanations should have at least as many columns as inputs samples!" + assert len(out["samples_explanations"].index) == len(out["inputs_samples"].index), ( + "Samples explanations should have the same number of rows as inputs samples!" + ) + assert len(out["samples_explanations"].columns) >= len(out["inputs_samples"].columns), ( + "Samples explanations should have at least as many columns as inputs samples!" + ) # - alerting service assert "Explanations Job Finished" in capsys.readouterr().out, "Alerting service should be called!" diff --git a/tests/jobs/test_training.py b/tests/jobs/test_training.py index 44c804d..973cdcb 100644 --- a/tests/jobs/test_training.py +++ b/tests/jobs/test_training.py @@ -86,32 +86,32 @@ def test_training_job( assert out["targets"].ndim == out["targets_"].ndim == 2, "Targets should be a dataframe!" # - lineage assert out["inputs_lineage"].name == "inputs", "Inputs lineage name should be inputs!" - assert ( - out["inputs_lineage"].source.uri == inputs_reader.path - ), "Inputs lineage source should be the inputs reader path!" + assert out["inputs_lineage"].source.uri == inputs_reader.path, ( + "Inputs lineage source should be the inputs reader path!" + ) assert out["targets_lineage"].name == "targets", "Targets lineage name should be targets!" - assert ( - out["targets_lineage"].source.uri == targets_reader.path - ), "Targets lineage source should be the targets reader path!" + assert out["targets_lineage"].source.uri == targets_reader.path, ( + "Targets lineage source should be the targets reader path!" + ) assert out["targets_lineage"].targets == schemas.TargetsSchema.cnt, "Targets lineage target should be cnt!" # - splitter - assert len(out["inputs_train"]) + len(out["inputs_test"]) == len( - out["inputs"] - ), "Train and test inputs should have the same length as inputs!" - assert len(out["targets_train"]) + len(out["targets_test"]) == len( - out["targets"] - ), "Train and test targets should have the same length as targets!" - assert ( - len(out["train_index"]) == len(out["inputs_train"]) == len(out["targets_train"]) - ), "Train inputs and targets should have the same length!" - assert ( - len(out["test_index"]) == len(out["inputs_test"]) == len(out["targets_test"]) - ), "Test inputs and targets should have the same length!" + assert len(out["inputs_train"]) + len(out["inputs_test"]) == len(out["inputs"]), ( + "Train and test inputs should have the same length as inputs!" + ) + assert len(out["targets_train"]) + len(out["targets_test"]) == len(out["targets"]), ( + "Train and test targets should have the same length as targets!" + ) + assert len(out["train_index"]) == len(out["inputs_train"]) == len(out["targets_train"]), ( + "Train inputs and targets should have the same length!" + ) + assert len(out["test_index"]) == len(out["inputs_test"]) == len(out["targets_test"]), ( + "Test inputs and targets should have the same length!" + ) # - outputs assert out["outputs_test"].shape == out["targets_test"].shape, "Outputs should have the same shape as targets!" - assert ( - len(out["test_index"]) == len(out["outputs_test"]) == len(out["inputs_test"]) - ), "Outputs should have the same length as inputs!" + assert len(out["test_index"]) == len(out["outputs_test"]) == len(out["inputs_test"]), ( + "Outputs should have the same length as inputs!" + ) # - i and score assert out["i"] == len(job.metrics), "i should be the number of metrics computed!" assert float("-inf") < out["score"] < float("+inf"), "Score should be between 0 and 1!" diff --git a/tests/jobs/test_tuning.py b/tests/jobs/test_tuning.py index 1da45d5..26cae43 100644 --- a/tests/jobs/test_tuning.py +++ b/tests/jobs/test_tuning.py @@ -66,13 +66,13 @@ def test_tuning_job( assert out["targets"].ndim == out["inputs_"].ndim == 2, "Targets should be a dataframe!" # - lineage assert out["inputs_lineage"].name == "inputs", "Inputs lineage name should be inputs!" - assert ( - out["inputs_lineage"].source.uri == inputs_reader.path - ), "Inputs lineage source should be the inputs reader path!" + assert out["inputs_lineage"].source.uri == inputs_reader.path, ( + "Inputs lineage source should be the inputs reader path!" + ) assert out["targets_lineage"].name == "targets", "Targets lineage name should be targets!" - assert ( - out["targets_lineage"].source.uri == targets_reader.path - ), "Targets lineage source should be the targets reader path!" + assert out["targets_lineage"].source.uri == targets_reader.path, ( + "Targets lineage source should be the targets reader path!" + ) assert out["targets_lineage"].targets == schemas.TargetsSchema.cnt, "Targets lineage target should be cnt!" # - results assert out["results"].ndim == 2, "Results should be a dataframe!" diff --git a/tests/utils/test_signers.py b/tests/utils/test_signers.py index 9554d97..5d1eced 100644 --- a/tests/utils/test_signers.py +++ b/tests/utils/test_signers.py @@ -12,9 +12,9 @@ def test_infer_signer(inputs: schemas.Inputs, outputs: schemas.Outputs) -> None: # when signature = signer.sign(inputs=inputs, outputs=outputs) # then - assert set(signature.inputs.input_names()) == set( - inputs.columns - ), "Signature inputs should contain input column names." - assert set(signature.outputs.input_names()) == set( - outputs.columns - ), "Signature outputs should contain output column names." + assert set(signature.inputs.input_names()) == set(inputs.columns), ( + "Signature inputs should contain input column names." + ) + assert set(signature.outputs.input_names()) == set(outputs.columns), ( + "Signature outputs should contain output column names." + ) diff --git a/tests/utils/test_splitters.py b/tests/utils/test_splitters.py index 6c0ef44..1c9217c 100644 --- a/tests/utils/test_splitters.py +++ b/tests/utils/test_splitters.py @@ -37,9 +37,9 @@ def test_time_series_splitter(inputs: schemas.Inputs, targets: schemas.Targets) assert n_splits == len(splits), "Splitter should return the given n splits!" for i, (train_index, test_index) in enumerate(splits): assert len(test_index) == test_size, "Test index should have the given test size!" - assert len(train_index) == ( - len(inputs) - test_size * (n_splits - i) - ), "Train index should have the cumulative remaining size!" + assert len(train_index) == (len(inputs) - test_size * (n_splits - i)), ( + "Train index should have the cumulative remaining size!" + ) assert train_index.max() < test_index.min(), "Train index should always be lower than test index!" assert not inputs.iloc[train_index].empty, "Train index should be a subset of the inputs!" assert not inputs.iloc[test_index].empty, "Test index should be a subset of the inputs!" From 9a9014623af32f0a423991404eae6f613b0b2747 Mon Sep 17 00:00:00 2001 From: lgcorzo Date: Tue, 28 Apr 2026 21:35:14 +0200 Subject: [PATCH 3/3] Fix Docker build: install poetry-plugin-export Poetry 2.0 requires an explicit plugin for the 'export' command. --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index f05b365..49f01d1 100644 --- a/Dockerfile +++ b/Dockerfile @@ -4,7 +4,7 @@ FROM python:3.12-slim AS builder WORKDIR /build # Install Poetry and export plugin -RUN pip install poetry==2.0.1 +RUN pip install poetry==2.0.1 poetry-plugin-export # Copy dependency files COPY pyproject.toml poetry.lock README.md ./